Expected expression before char in C - c

I am doing a word search program and keep getting the same error that doesn't give me much information about whats wrong. Specifically it says this...
wordSearch.c:38:32: error: expected
expression
returnWord = (char *) strstr(char const *sentence, char const *phrase);
^
^
what could this be?

returnWord = char *strstr(const char *sentence, const char *phrase);
is not how you call a function. Get rid of the return type, simply use
returnWord = strstr(sentence, phrase);
assuming sentence and phrase are variables are defined and having proper values.

Based on the pictures, it looks as if something is wrong with strstr. This makes sense because of the way you are passing arguments. strstr expects two const char * arguments, however you have casted them incorrectly. Additionally, since strstr already returns a char * there is no need to cast that. Thus, line 38 should be returnword = strstr((const char *) sentence, (const char *) phrase);

Related

Using snprintf to concatenate giving segmentation fault in c

I am trying to compare szFileName1 and szFileName2 , if they are not same, then I am renaming it, but when I am trying to concatenate using snprintf it's giving segmentation fault.what mistake am I doing here?
typedef struct{
char filePath[100];
} filectx;
void filename1(filectx *ctx, const char ** szFileName1){
*szFileName1 = ctx->filepath;
}
void filename2(const char ** szFileName2){
char buf[20] = "/usr/bin/abb.txt";
snprintf(szFileName2, sizeof(szFileName2), "%s%s", szFileName2, buf);
}
int main(){
const char* szFileName1 = NULL;
const char *szFileName2 = malloc(100);
filectx ctx;
ctx.filePath = "/usr/bin/abc.txt";
filename1(&ctx, &szFileName1);
filename2(&szFileName2);
if(strcmp(szFileName1, szFileName2) != 0){
const char szFilePath1[200] = "/local/";
const char szFilePath2[200] = "/local/";
snprintf(szFilePath1, sizeof(szFilePath1), "%s%s", szFilePath1, szFileName1);
snprintf(szFilePath2, sizeof(szFilePath2), "%s%s", szFilePath2, szFileName2);
int ret = rename(szFilePath1, szFilePath2);
}
free(szFileName2);
return 0;
}
I think the problem here is with the arguments you pass to snprintf().
snprintf() expects an argument of type string ("char *"), but not "char **".
Here you are passing a pointer instead of the actual string. So when it tries to access the address it gives segmentation fault.
Change the parameters in the functions filename1() and filename2() to "char *" type and see. It should work.
Hope this helps.
Kranthi
With
const char szFilePath1[200] = "/local/";
const char szFilePath2[200] = "/local/";
as well as others as your function arguments, you declare those variables const. You then try to write to them with snprintf. Don't make these const.
You also can't reuse a variable as source and destination in snprintf.
I'm surprised that the compiler allowed you to compile this.
Although snprintf() doesn't work in your case, why don't you use strcat() or strncat()?
Instead of
snprintf(szFilePath1, sizeof(szFilePath1), "%s%s", szFilePath1, szFileName1);
you can write
strncat(szFilePath1, szFileName1, strlen(szFilePath1));
And by the way:
WHY did you write
sizeof(szFilePath1)
?
So, points to improve
In the very beginning:
*szFileName1 = ctx->filepath;
Not a nice thing to do. It's better to use strcpy()/strncpy(). And passing char ** argument also looks pretty strange.
Stated above. Usage of snprintf's

how to set char array to string in c

so i have a struct call Process_Info
struct Process_Info {
char name[128];
int pid;
int parent_pid;
int priority;
int status;
};
and an array of Process_Info call info. I set pid in info to an integer, it works but when I try to set name in info to "{kernel}" like this
info[i].name="{kernel}";
and it give me incompatible type in assignment error. I search online it seem i can do this, like in http://www.cs.bu.edu/teaching/cpp/string/array-vs-ptr/, they did char label[] = "Single"; So what am i doing wrong?
The short answer: A C compiler will bake constant strings into the binary, so you need to use strncpy (or strcpy if you aren't worried about security) to copy "{kernel}" into info[i].name.
The longer answer: Whenever you write
char label[] = "Single";
the C compiler will bake the string "Single" into the binary it produces, and make label into a pointer to that string. In C language terms, "Single" is of type const char * and thus cannot be changed in any way. However, you cannot assign a const char * to a char *, since a char * can be modified.
In other words, you cannot write
char label[] = "Single";
label[0] = "T";
because the compiler won't allow the second line. However, you can change info[i].name by writing something like
info[i].name[0] = '[';
because info[i].name if of type char *. To solve this problem, you should use strncpy (I referenced a manual page above) to copy the string "{Kernel}" into info[i].name as
strncpy(info[i].name, "{Kernel}", 256);
info[i].name[255] = '\0';
which will ensure that you don't overflow the buffer.
I think you may be mistaken. The way you would assign this would be one char at a time like so...
name[] = {'a','b','c','d'};

casting char * to char[]

Example:
char str[10];
gets(str);
str = (char[10]) strtok(str, " "); // type error here
Since strtok() returns a char *, I get an type error without that casting. With it I get the following:
error: cast specifies array type
What is the best to fix this code?
Oh man, be careful with that gets()! Related question
You can't assign to arrays (in other words, use them as lvalues).
char *p = "string";
char array[10];
array = p; /* invalid */
Apart from that, you're not using strtok() correctly. The pointer returned points to the subsequent token, so you might want to create a separate char pointer to store it.
You should be assigning the result of strtok into a separate char* variable. You can't assign it back into str.
You should not be assigning the reult of strtok() back to your str variable in the first place. Use a separate variable instead, eg:
char str[10];
gets(str);
char *token = strtok(str, " ");
//use token as needed...
You cannot assign anything to an array. Even this simplistic program will fail:
char *foo(void) { }
int main(int argc, char *argv[])
{
char a[1];
a = foo();
return 0;
}
As indeed it does:
$ make fail
cc fail.c -o fail
fail.c: In function ‘main’:
fail.c:7:4: error: incompatible types when assigning to type ‘char[1]’ from type ‘char *’
make: *** [fail] Error 1
Either re-define str as char *str or figure out some other way to re-write your program to not attempt to assign to an array. (What does the surrounding code look like? The code you've pasted doesn't really make sense anyway...)
You can get parameter before calling your function:
char mystr[] = "192.168.0.2";
split_ip(myster[]);
char * split_ip( char ip_address[]){
unsigned short counter = 0;
char *token;
token = strtok (ip_address,".");
while (token != '\0')
{
printf("%s\n",token);
token = strtok ('\0', ".");
}
}// end of function def

Converting char * to char * const *

Do excuse me to the basic"ness" of this question. I am at a loss with pointers at times. I have a char * but I need to convert it to a char * const * to be able to correctly use it in the fts() function. How do i do that?
Thanks
You are not supposed to do that kind of conversion, because the types are not compatible.
About pointers and pointers to pointers
char * is a pointer to a string of characters, whereas char ** is an pointer to a pointer to a string of characters. (the const is a bonus). This probably means that instead of supplying a string of characters, you should provide an array of string of characters.
Those two things are clearly incompatible. Don't mix them with a cast.
About the fts_* API
To find the solution to your problem, we need to read the fts_* function API (e.g. at http://linux.die.net/man/3/fts), I see that:
FTS *fts_open(char * const *path_argv, int options,
int (*compar)(const FTSENT **, const FTSENT **));
with your char * const * parameter path_argv, the description explains:
[...] If the compar() argument is NULL, the directory traversal order is in the order listed in path_argv for the root paths [...]
which confirms that the fts_open function is really expected a collection of paths, not one only path.
So I guess you need to pass to it something like the following:
char *p[] = { "/my/path", "/my/other/path", "/another/path", NULL } ;
About the const
Types in C and C++ are read from right to left. So if you have:
char * : pointer to char
char const * : pointer to const char (i.e. you can't modify the pointed string, but you can modify the pointer)
const char * : the same as char const *
char * const : const pointer to char (i.e. you can modify the pointed string, but you can't modify the pointer)
char ** : pointer to pointer to char
char * const * : pointer to const pointer to char (i.e. you can modify the pointer, and you can modify the strings of char, but you can't modify the intermediary pointer
It can be confusing, but reading them in the right-to-left order will be clear once you are more familiar with pointers (and if you programming in C or C++, you want to become familiar with pointers).
If we go back to the initial example (which sends a bunch of warnings on gcc with C99) :
char ** p = { "/my/path", "/my/other/path", "/another/path", NULL } ;
I played with the API, and you can feed it your paths two ways:
char * p0 = "/my/path" ;
char * p1 = "/my/other/path" ;
char * p2 = "/another/path" ;
/* with a fixed-size array */
char * pp[] = {p0, p1, p2, NULL} ;
FTS * fts_result = fts_open(pp, 0, NULL);
Edit 2011-11-10: snogglethorpe rightfully commented this solution is not a C89 valid solution, even if it compiles successfully with gcc (excluding pendantic + C89 flags). See Error: initializer element is not computable at load time for more info on that
or:
/* with a malloc-ed array */
char ** pp = malloc(4 * sizeof(char *)) ;
pp[0] = p0 ;
pp[1] = p1 ;
pp[2] = p2 ;
pp[3] = NULL ;
FTS * fts_result2 = fts_open(pp, 0, NULL);
free(pp) ;
Edit
After reading others answers, only two of them (mkb and moshbear) avoid the "just cast the data" error.
In my own answer, I forgot the NULL terminator for the array (but then I don't know the Linux API, nor the fts_* class of functions, so...)
I'm assuming you're talking about fts_open:
FTS *fts_open(char * const *path_argv, int options,
int (*compar)(const FTSENT **, const FTSENT **));
What it's wanting of you is an array of const char* pointers, ie. an array of strings. The const is there just to tell you that it's not going to modify your strings, and gives you the opportunity to pass const strings.
Non-const variables can be treated as const, however you shouldn't usually treat them the other way around.
The first argument is just like argv passed to main, you could just have:
char *path_argv[] = { "/first_path/", "/second_path/", NULL };
It's important that the last element is NULL to indicate the end of the array.
Note also that path_argv could also be declared as:
char **path_argv
OR*
char * const *path_argv
Any of these are suitable types to be passed as the first argument to fts_open. You do, however, obviously have to initialize it differently than the above, but those are other ways you can declare path_argv. I made that unclear previously.
And then just fts_open(path_argv, options, compar), where options is your options, and compar is your compare function.
You need to make a second array, which is NULL-terminated (because fts()'s first argument is argv).
E.g.
char *const buf2[2] = { buf, NULL };
fts(buf2);

Doubts in the strcpy function used

I am using two buffers which are of unsigned char and when I used the function strcpy, there is a compilation error which says "invalid conversion of unsigned char * to char *". Can anyone please tell me what difference does an unsigned buffer vs. signed buffer makes to the output? This is the program which I had tried.
main()
{
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
strcpy(buff,dst);
printf("The string is %s\n",buff);
}
Now when i typecast the parametrs passed in strcpy to (char *),This programe works fine as shown below
main()
{
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
strcpy((char *)buff,(char *)dst);
printf("The string is %s\n",buff);
}
2nd Question: Does typecasting to char* in the string function create any issues?
Please do let me know if you need any more inputs.
You can just change:
unsigned char buff[20] = "Michael";
unsigned char dst[20] = "Jackson";
to
char buff[20] = "Michael";
char dst[20] = "Jackson";
To think of it logically, A string cannot be signed or unsigned, it is not a numeric value to be treated that way, it is just an char array and you should declare and use it so.
Why do you get the error?
strcpy has the prototype:
char *strcpy(char *restrict s1, const char *restrict s2);
And what you are passing to it is, unsigned char*, when a function is called parameter type checking takes place and the compiler finds that you are not calling the function with proper type parameters and hence it complains about it, When you apply a cast the function arguments match and hence compilation passes.
Does typecasting to char in the string function create any issues?*
No, in this case it doesn't.
Though it makes more sense to change your usage of unsigned char for the reasons mentioned above in the answer.
Suggestion:
Strcpy is not safe, so you are much better off using strncpy, it allows you to explicitly specify how many characters to copy, rather than rely on null terminator of the source string, Also this helps avoiding buffer overflow since you explicitly specify a length.
The way you are using it should be fine.
But you shouldn't use unsigned char arrays with string handling functions. In C strings are char arrays, not unsigned char arrays. Since passing to strcpy discards the unsigned qualifier, the compiler warns.
As a general rule, don't make things unsigned when you don't have to.
strcpy wants char *'s, plain and simple. Cast your buffers to char *'s and you'll be fine. Then there's the whole safety problem with using strcpy in the first place...

Resources