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
Related
I am new to C. Was writing this so it takes the strings from the passed array and makes it a single sentence. But I got this error, I am not good with arrays in C. I can use some help from you guys. I did search an answer for this and couldn't find.
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
char smash(char arr[20][20]) {
char tmp[sizeof(arr)/sizeof(arr[0])];
for (int i=0; i < sizeof(arr)/sizeof(arr[0]); i++) {
strcat(tmp, arr[i]);
strcat(tmp, " ");
}
return tmp;
}
int main(){
char list[][6] = {"hello", "world"};
printf("%s", smash(list[]));
}
Error
error: expected expression before ']' token
printf("%s", smash(list[]));
^
There are quite a number of errors in this small piece of code.
First, to address the compiler error: list[] is not a valid expression. If you want to pass list to the function, leave the braces out:
printf("%s", smash(list));
This will then bring up another error. The function is expecting a char [20][20] as it's argument, but that's not what you're passing in. Since arrays as parameters are converted to a pointer, the argument type is actually char (*)[20] i.e. a pointer to an array of char of size 20. Note also that this conversion only occurs for the outermost array dimension, not all.
Since you're passing in a char [2][6] which gets converted to a char (*)[6] this is a type mismatch. So change the parameter to char arr[][6].
Then you're attempting to get the size of the array parameter inside of the function:
sizeof(arr)/sizeof(arr[0])
Since arrays cannot be directly passed to a function due to the conversion mentioned earlier, arr is actually a pointer and not an array, so you won't get the result you expect from this. You'll need to pass the number of array elements as a separate parameter.
Then you're calling strcat on tmp. This function will only work if the destination already has a null terminated string in it. Since tmp was not initialized or written to prior to the first call to strcat, you end up reading uninitialized bytes and potentially past the end of the array which will trigger undefined behavior.
This can be fixed by setting the first byte of the array to 0 before the loop to make it an empty string:
tmp[0] = 0;
for ...
Then there's the problem with the return type. The function is declared to return a char but you're giving a char * to the return statement, and at the point the function is called it is passed to printf where the %s format specifier is expecting a char * parameter.
So change the return type of the function from char to char *.
Finally, you're returning a pointer to a local variable in the function. This variable's lifetime ends when the function returns, so the returned pointer is invalid and using it will also trigger undefined behavior.
You'll need change tmp to a pointer and dynamically allocate memory for it using malloc. This also means you'll need to save the return value of the function in a separate variable which you can then pass to printf to print and then pass to free to free the memory.
After making all this changes, the resulting code should look like this:
char *smash(char arr[][6], int len) {
// enough for len strings plus len spaces
char *tmp = malloc(sizeof(arr[0]) * len + len + 1);
tmp[0] = 0;
for (int i=0; i < len; i++) {
strcat(tmp, arr[i]);
strcat(tmp, " ");
}
return tmp;
}
int main(){
char list[][6] = {"hello", "world"};
char *result = smash(list, sizeof(list)/sizeof(list[0]));
printf("%s", result);
free(result);
return 0;
}
I was just playing around with some code, and ended up typing something along the lines of the following piece of code. The issue seems to be that the char *string line isn't actually interchangeable with a char string[], but I can't seem to wrap my head around why strtok(...) throws a "segmentation violation" if my argument is initialized as a char* to a string, or why it would even require an initialization of char[] instead?
#include <stdio.h>
#include <string.h>
//extern char *strtok (char *__restrict __s, const char *__restrict __delim);
char *string = "Hello world whats up?";
/*
SEGV - Must be char string[] in order to execute.
e.g. char string[] = "Hello world whats up?";
*/
char *delim = "\t ";
char *token;
int main (argc, argv)
int argc;
char **argv;
{
token = strtok(string, delim);
while ( token != NULL ) {
printf("%s\n", token);
token = strtok(NULL, delim);
}
}
The strtok function (potentially) modifies the string passed to it as its first argument. That is the critical point, here.
In your code snippet (not using the [] version), your string variable is initialized to be the address of a string literal. That literal is a constant and is likely to be placed in read-only memory. Thus, when you call strtok and that function finds a delimiter character, it attempts to replace that character with a nul, which would require writing to memory to which it does not have the required access – and your program crashes.
However, in your version using the [] syntax, you are declaring a (modifiable) array of characters and initializing it with a copy of the string literal.
In summary:
char* pc = "Hello, World!"; // pc points to a CONSTANT string literal
char ca[] = "Hello, World!"; // ca is a 'normal' array initialized with data
In C all literal strings are non-modifiable, they are in essence read-only.
When you define and initialize string you make it point to the first character of such a literal string.
This is the reason it's recommended to use const char * for literal strings.
If you want to modify the string in any way, and strtok modifies the string it tokenizes, then you must use an explicit modifiable array.
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);
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
I am trying to get a token from a string that is delimited by space(" "). But the following code crashes the application when the string is of char * type.
#include <stdio.h>
#include <string.h>
int main(){
char *str1 = "Hello World!"; //char str1[] works
char *token;
char *savePtr;
token = strtok_s(str1, " ", &savePtr);
printf("%s", token);
return 0;
}
I also get the following warnings:
C:\Users\Haris\Desktop\C files>gcc firstProgram.c -o firstprogram.exe
firstProgram.c: In function 'main':
firstProgram.c:10:9: warning: implicit declaration of function 'strtok_s' [-Wimplicit-function-declaration]
token = strtok_s(str1, " ", &savePtr);
^
firstProgram.c:10:7: warning: assignment makes pointer from integer without a cast [-Wint-conversion]
token = strtok_s(str1, " ", &savePtr);
The strtok_s function modifies the thing the pointer points to, turning delimiters into zeroes. So it cannot take a pointer to a constant. But you pass it str1, which is a pointer to a string constant. When it tries to modify that string to turn the delimiters into zeroes, it tries to modify a constant. That is, of course, illegal.