C Problem statement: Search an array of integers to find the first first negative integer, if one exists , return its position in the array.
I am aware that I can do this by using indexing, however, I am just wondering why is the program not going into the if condition? Even if I do the casting the code never goes inside if condition.
void find_negative(int argc, char *argv[])
{
int i = 0;
//ignore the first string of arguments because it will be "./problem1.3.c"
for(i =1; i<argc;i++)
{
if(*(argv+i)==2) <-------------------------this is where I get stuck (problem)
{
printf("found it at %d location.\n", i);
}
else
{
printf("All positive.\n");
}
}
}
int main(int argc , char *argv[])
{
find_negative(argc, argv);
return 0;
}
The type of (argv+i) is char**.
The type of *(argv+i) is char*.
In the line,
if(*(argv+i)==2)
you are trying to compare a char* with 2, whose type is int. That explains the compiler error messages.
Perhaps you want to extract an integer from the argument and compare it with 2. Then, you need to use:
if(atoi(*(argv+i))==2)
Some things to note:
*(argv + i) is exactly equivalent to argv[i]. There is no difference whatsoever in this particular code.
argv has type char ** (a pointer to a pointer to char), so *(argv + i) has type char * (a pointer to char). You are comparing this directly to the integer value 2, which is why the compiler is giving you grief, because it is rare to ever compare pointers to integers.
Comparing a string "2" to an integer value 2 won't work, they are different types entirely. If the program is receiving its input via command line arguments, you should parse the input into an actual binary integer.
As an example:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char *argv[])
{
for (int i = 1; i < argc; i++)
{
long value = strtol(argv[i], NULL, 10);
if (value < 0)
{
printf("Found a negative integer at position %d\n", i);
return 0;
}
}
// if we get here then there were no negative integers in the input
puts("No negative integers in input");
return 1;
}
The function I used above is documented here.
The input, argv is an array of characters. You probably first need to parse it and convert it to an array of integers.
Related
I'm a beginner at C, working through 'Crack' on pset2 of CS50. I'm trying to compare argv[1] with a string called hash, which is an output of C's crypt function.
The code produces the following error:
runtime error: null pointer passed as argument 1, which is declared to never be null
/usr/include/string.h:137:33: note: nonnull attribute specified here
I could use some help understanding what this error means and how it is caused, so I can find a way around it. I've searched for similar problems but haven't been able to understand the precise cause. The code runs without errors until the last 'if' statement appears.
#include <stdio.h>
#include <crypt.h>
#include <math.h>
#include <cs50.h>
#include <string.h>
int main(int argc, string argv[])
{
if (argc != 2)
{
printf("Usage: ./crack hash"); // Error message for incorrect usage
return 1;
}
else
{
char slt_str[3], slt1[1], slt2[1], pwd[5];
string hash;
for (int i = '.'; i <= 'z'; i++) //first character of salt
{
for (int j = '.'; j <= 'z'; j++) //second character of salt permuted against first
{
slt1[0] = i, slt2[0] = j; //arrays to hold first and second character of salt respectively
slt_str[0] = slt1[0]; // 1st char of salt array is first char of first partial salt array
slt_str[1] = slt2[0]; // 2nd char of salt array is 1st char of 2nd partial salt array
slt_str[2] = '\0'; // 3rd character of salt array is null zero
//printf("\n%s",crypt("abc", slt_str));
// salt + permutation code to go here //
for (int k = 'A'; k <= 'z'; k++)
{
pwd[0] = k;
pwd[1] = '\0';
//printf("%s\n", crypt(pwd, slt_str));
hash = crypt(pwd, slt_str);
//printf("%s", crypt(pwd, slt_str));
if (strcmp(argv[2], hash) == 0)
{
printf("%c", pwd[0]);
}
}
}
}
}
}
You must check the return code from crypt() as it may be NULL to indicate an error. An error may be caused by invalid characters in salt which is typically restricted to the set [a-zA-Z0-9./].
The declaration for main is potentially incorrect (what is string?). It should be:
int main(int argc, char *argv[])
You are accessing the wrong array element. In C, arrays are indexed starting at 0. If you want the 'second' element, say argv[1]:
Change:
if (strcmp(argv[2], hash) == 0)
... to:
if (strcmp(argv[1], hash) == 0)
Question: Write a program anagram that sorts the letters in a word, which is useful when searching for anagrams. anagram takes a single argument, which is a string containing only lower-case letters, sorts the letters alphabetically, and then prints the sorted letters. You may use any sorting algorithm you are familiar with, but you must write the sort function yourself. You may not use any sort function provided by a library.
Usage
$ ./anagram hello
ehllo
$ ./anagram positivity
iiiopsttvy
$ ./anagram abcdef
abcdef
The below code is what I have done so far but I get the error
passing char * to parameter of unsigned char converts between pointers to integer types with different sign
#include <stdio.h>
#include <string.h>
void anagram(unsigned char input[])
{
int count[256] = { 0 };
int i;
for (i = 0; input[i] != '\0'; i++)
{
count[input[i]]++;
}
for (i = 0; i < 256; i++)
{
while (count[i] > 0)
{
printf("%c", i);
count[i]--;
}
}
}
int main(int argc, char* argv[])
{
if(argc > 1)
{
anagram(argv[1]);
}
return 0;
}
The short answer to your question is you are getting the pointer sign mismatch warning because you are attempting to pass argv[1] (type char *) to anagram which you have declared with a parameter of unsigned char * (though you use input[], the practical effect is that input decays to a pointer when used as a parameter)
The simple solution while preserving the unsigned char* type for anagram is to cast argv[1] to (unsigned char *) when passed as a parameter to anagram, e.g.
anagram((unsigned char *)argv[1]);
The more practical question is "Do you really need the unsigned char* type to begin with?" While you can escape and pass non-ASCII values as the argument to your program -- is that something you expect and want to protect against by using the unsigned char* (which is 100% fine to do).
Generally, you would simply declare anagram (char *input) (which is your second alternative to eliminate the signed mismatch on the pointers) and limit your loop to looping over the valid range for ASCII characters (see ASCIItable.com)
Either way is fine so long as you handle the pointer signedness consistently. Putting that altogether and removing the magic numbers from your code, you could do something similar to the following:
#include <stdio.h>
#include <string.h>
#define CHRSET 256 /* if you need a constant, define one */
void anagram (unsigned char *input)
{
int i, count[CHRSET] = { 0 };
for (i = 0; input[i] != '\0'; i++)
count[input[i]]++;
for (i = 0; i < CHRSET; i++)
while (count[i] > 0) {
printf("%c", i);
count[i]--;
}
putchar ('\n'); /* provide a POSIX compliant newline before termination */
}
int main(int argc, char *argv[]) {
if (argc < 2) {
fprintf (stderr, "error: insufficient input\n"
"usage: %s <string>\n", argv[0]);
return 1;
}
anagram ((unsigned char *)argv[1]);
return 0;
}
(note: you can also move the output of the final newline to main, but unless you plan on smushing multiple sorted strings together by making repeated calls to anagram, then it is better left after the output of each string)
Look things over and let me know if you have further questions.
I am trying to set my pointer (numProcesses) equal to the command line argument entered in my program (it is an int value that gets stored in argv[1]). My question is how do I get numProcess to equal argv[1] value. Every time I try a different way of doing it, I get the address location of argv[1] instead of its content. I know how pointers work for the most part. I have no problem getting this to work in c++ but I am new to C so having a little bit of a rough time. Below is my code and I appreciate any help/tips thank you.
void parentInfo(int *numProcesses);
int main (int argc, int *argv[])
{
//Creates a command line argument that stores an integer
int *numProcesses = (int *)malloc(sizeof(12));
if (argc < 2)
{
printf("\n\nUsage: %s <enter a number (12 or less)>\n\n", argv[0]);
exit (-1);
}
else
{
numProcesses = argv[1];
printf("numProcesses = %d", numProcesses);
if(*numProcesses > 12 || *numProcesses < 1)
{
printf("\n\nUsage: %s <enter a number (12 or lrss)>\n\n", argv[0]);
}
else
{
parentInfo(numProcesses);
}
}
return 0;
}
First of all, argv[1] is a char *. There's no such thing as "argv[1]'s content" - argv[1] is a pointer to some location in the memory which (if we're lucky) contains a string.
What you actually need is a way to convert a string into a number. Well, there's atoi:
numProcesses = atoi(argv[1]);
#include <stdlib.h>
void parentInfo (int *numProcesses);
int main (int argc, char* argv[])
{
int num = atoi (argv[1]); // no error checking!
parentInfo (&num);
return 0;
}
Use strtol instead of atoi if you need error checking; which you probably would.
For exercising my programming skills in C I'm trying to write the strncpy function by myself. Doing that I kept hitting errors, solving most of them eventually I'm stuck with no further inspiration to go on.
The error I receive is:
ex2-1.c:29:3: warning: format ‘%s’ expects argument of type ‘char *’, but argument 2 has type ‘int’ [-Wformat=]
printf("The copied string is: %s.\n", stringb);
The thing is that it's a very common error and that it's also already described on SO, only I can't seem to apply the tips other people have already pointed out. I get that I'm using a wrong type when printing the variable, and when I use the %d format it will return an integer which is probably the ASCII value of the first character, as it doesn't change when increasing the max number of bytes to copy.
Using GDB I've found out that the b variable when done iterating through the while loop holds the correct string, still I can't seem to print it.
I'm probably lacking a very fundamental part of knowledge about the C language and I apologise for asking this novice question (once again). Also I would appreciate it if you could give feedback or point out other flaws in my code.
#include <stdlib.h>
#include <stdio.h>
void strmycpy(char **a, char *b, int maxbytes) {
int i = 0;
char x = 0;
while(i!=maxbytes) {
x = a[0][i];
b[i] = x;
i++;
}
b[i] = 0;
}
int main (int argc, char **argv) {
int maxbytes = atoi(argv[2]);
//char stringa;
char stringb;
if (argc!=3 || maxbytes<1) {
printf("Usage: strmycpy <input string> <numberofbytes>. Maxbytes has to be more than or equal to 1 and keep in mind for the NULL byte (/0).\n");
exit(0);
} else {
strmycpy(&argv[1], &stringb, maxbytes);
printf("The copied string is: %s.\n", stringb);
}
return 0;
}
There is a slight difference between char and char*. The first is a single character whereas the later is a pointer to char (which can point to variable number of char objects).
The %s format specifier really expects a C-style string, which should not only be of type char* but is also expected to be null-terminated (see C string handling). If you want to print a single character, then use %c instead.
As for the program, assuming that what I think you want is what you want, try something like this:
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
static void strmycpy(char *dest, const char *src, size_t n) {
char c;
while (n-- > 0) {
c = *src++;
*dest++ = c;
if (c == '\0') {
while (n-- > 0)
*dest++ = '\0';
break;
}
}
}
int main(int argc, char *argv[]) {
size_t maxbytes;
char *stringb;
if (argc != 3 || !(maxbytes = atoll(argv[2]))) {
fprintf(
stderr,
"Usage: strmycpy <input string> <numberofbytes>.\n"
"Maxbytes has to be more than or equal to 1 and keep "
"in mind for the null byte (\\0).\n"
);
return EXIT_FAILURE;
}
assert(maxbytes > 0);
if (!(stringb = malloc(maxbytes))) {
fprintf(stderr, "Sorry, out of memory\n");
return EXIT_FAILURE;
}
strmycpy(stringb, argv[1], maxbytes);
printf("The copied string is: %.*s\n", (int)maxbytes, stringb);
free(stringb);
return EXIT_SUCCESS;
}
But frankly speaking, this is so fundamental that explaining might just result in writing a book on C. So you will be a lot better off if you just read one already written. For a list of good C books and resources, see The Definitive C Book Guide and List
Hope it helps. Good Luck!
For example,
#include <stdio.h>
int main (int argc, const char * argv[]) {
char out = printf("teststring");
printf("%d\n", out);
return 0;
}
will return teststring10. Anyone has an idea how to get rid of the 10?
Thanks in advance.
Lets look at your code:
#include <stdio.h>
int main (int argc, const char * argv[]) {
char out = printf("teststring");
printf("%d\n", out);
return 0;
}
And change it:
#include <stdio.h>
int main (int argc, const char * argv[]) {
const char *str = "teststring";
int out = printf("%s", str);
printf("\nPrintf wrote %d bytes when printing %s\n", out, str);
return 0;
}
Compile / run the edited version and you should immediately see the difference. Modify the length of str then compile and run it again.
Now, just a tiny change to your original code:
#include <stdio.h>
int main (int argc, const char * argv[]) {
char out = printf("teststring\n");
printf("%d\n", out);
return 0;
}
You can see now, you are printing two different things, and out has become 11, since a newline was added. Nothing is actually trailing here. Then change %d to %c (the correct format specifier for out in your example) and notice the difference. ASCII (11) is a vertical tab (see here). YTMV (your terminal may vary). Here, you printed a character, not a character representation of an integer.
The actual type that printf() returns is int, which is an integer. The reason for this is so that you know exactly how many bytes printf() actually printed. This typical for that family of functions, but more useful for functions like snprintf() so you can know if it could not print the entire length of any given format to a buffer. Note that the return type is signed, it can be negative, so the storage type you pick to store its value matters quite a bit, especially if you work with that value while assuming that its greater than or equal to zero.
Here is a handy tutorial to format specifiers you can use with the printf() family of functions. More importantly, check the return type of the functions that you are using.
I also suggest spending some quality time with this book, be sure to work through the exercises as time permits. Its the best self-study course in C and the exercises are fun. When you get a solid grasp of C, work through the exercises again .. then compare your answers, its eye opening :)
the 10 is because of the
printf("%d\n", out);
printf return the number of characters written to the output stream
the length of "teststring" which is 10 assigned to "out"
and the n you print the value of out - so 10 is printed.
int main(int argc, char *argv[])
{
const char *str = "This is a constant string";
printf("%s\n", str);
return 0;
}
%s is the format specifier for a string. %d is the format specifier for a decimal representation of an integer. printf will return the number of characters written to the output.
#include <stdio.h>
int main (int argc, const char * argv[]) {
char out = printf("teststring");
printf("%d\n", out);
return 0;
}
Assuming that you want to assign "out" to a function (as I think you've said somewhere):
#include <stdio.h>
int main (int argc, const char * argv[])
{
char *out = NULL;
out = funcReturns("teststring");
printf("%s\n", out);
return 0;
}
If you allocate the memory inside the function that returns "teststring" then I think you need to make the return value static. For example (code untested):
char *funcReturns(char *returnStr)
{
static char *returnThis = NULL;
returnThis = strdup(returnStr);
return returnThis;
}
int printf ( const char * format, ... );
On success, the total number of characters written is returned.
When you execute this:
char out = printf("teststring");
The string "teststring" will be printed on your screen, and the value 10 will be
atrib to variable out.
Notice that the print cursor will be kept on the current line at the end of "teststring", once you did not put sufix '\n' on the end of string.
So, when you execute printf("%d\n", out); on the next line, the program will print the value 10 just after "teststring", and you will see "teststring10 on your screen."
If you really want to get rid of the 10 just remove the line printf("%d\n", out); from your code...
int main (int argc, const char * argv[]) {
int out = printf("teststring\n");
/* printf("%d\n", out); */
return 0;
}