The dreaded warning: passing argument 1 of ... makes integer from pointer without a cast
I just don't understand this. All I am trying to do is to pass a simple string (yes, I know a character array) to a function. The function parses the string and returns the first part. Can somebody please show me what I am doing wrong? Thank you!
char* get_request_type(char* buffer) {
char* p;
p = strtok(buffer, "|");
return p;
}
int main()
{
char buffer[30] = "test|something";
fprintf(stdout, "buffer: %s\n", buffer); //<-- looks great but needs parsing
char* request_type = get_request_type(buffer); //<-- error is here
fprintf(stdout, "%s\n", request_type); //<--expecting to see 'test'
}
There may yet come a day when I get comfortable working with strings in C, but that day is not this day...
You didn't include string.h, so the compiler will assume that strtok is defined as:
int strtok();
returns int and takes unknown number of arguments, it's call implicit function declaration. The solution is just to include string.h where strtok is declared.
This piece of the code works well. Post if there is still any problem.
#include<stdio.h>
#include<string.h>
char* get_request_type(char *buffer) {
char *p;
printf("----%s\n",buffer);
p = strtok(buffer, "|");
//fprintf("%s--->",p);
return p;
}
int main()
{
char buffer[30] = "test|something";
fprintf(stdout, "buffer: %s\n", buffer); //<-- looks great but needs parsing
char* request_type = get_request_type(buffer); //<-- No error here
fprintf(stdout, "request_type: %s\n", request_type);
return 0;
}
Related
I am trying to pass a string to a function and tokenize the string, but it gives me an access violation error when it tries to execute strtok.
int main(void) {
char String1[100];
// note: I read data into the string from a text file, but I'm not showing the code for it here
tokenize(String1);
return 0;
}
void tokenize(char data[]) {
strtok(data, ','); // gives me an access violation error
}
When I used strtok in main, it works, but not when I pass it to the function.
If your compiler is not giving you plenty of warnings about this code, please enable more warnings.
You need to #include <string.h> to get the prototype for strtok().
You either need a prototype for tokenize(), or more simply, just move its definition above main().
(Where your actual bug is) The second parameter of strtok() should be a char *, not a char. So change ',' to ",".
You should consult man strtok for more detail. And it's advisable to use strtok_r instead of strtok.
#include <stdio.h>
#include <string.h>
void tokenize(char data[]) {
char *token = data;
while (1) {
token = strtok(token, ",");
if (!token) {
break;
}
printf("token : %s\n", token);
token = NULL;
}
}
int main(void) {
char String1[] = "a,b,c,d,e,f,g";
// note: I read data into the string from a text file, but I'm not showing the
// code for it here
tokenize(String1);
return 0;
}
Am doing a task where am supposed to used getline function read input from a user from the terminal. Here is my code:
int main(int ac, char **av)
{
printf("Write something: \n");
char **buf = NULL;
size_t buf_size = 0;
ssize_t bytes_read = getline(buf, &buf_size, stdin);
if (bytes_read != -1)
write(STDOUT_FILENO, buf, buf_size);
else
printf("An error occured\n");
free(buf);
return (0);
}
From the code above. My program displayed the text: An error occurred.
Did some code refactoring and this is what I came up with:
int main(int ac, char **av)
{
printf("Write something: \n");
char *buf = NULL;
size_t buf_size = 0;
ssize_t bytes_read = getline(&buf, &buf_size, stdin);
if (bytes_read != -1)
write(STDOUT_FILENO, buf, buf_size);
else
printf("An error occured\n");
free(buf);
return (0);
}
Voila! The code displayed whatever was inputted, just what I wanted. So I fixed my the issue. But what am trying to understand is what's wrong the first code snippet? An it is right to do this?:
char **name = "John Doe";
or
char **name = NULL;
I did some quick test on an online compiler. Here is the code:
int main() {
// Write C code here
char **name = "John Doe";
printf("%p\n", name); //0x55f5f9890004
printf("%p\n", *name); //0x656f44206e686f4a
printf("%c\n", *name); //J
printf("%p", "John Doe"); //0x55f5f9890004
return 0;
}
I realised that the double pointer was just treated as a single char pointer. Not sure if my finding are right. If you can give a better explanation the above main function that would be cool.
When you want to change a variable in a function you need to pass it by reference. Otherwise the function will deal with a copy of the value of the original object used as an argument expression and changing the copy of the value will not influence on the value of the original object.
In C passing by reference means passing an object indirectly through a pointer to it.
Thus dereferencing the pointer the function will have a direct access to the original object and can change it.
In this code snippet
char *buf = NULL;
size_t buf_size = 0;
ssize_t bytes_read = getline(&buf, &buf_size, stdin);
you want that the pointer buf after calling the function getline would point to a string read in the function. So you need to pass it to the function by reference the same way as you are passing another variable buf_size the value of which is also changed within the function and the caller of the function needs to know the result value of the variable.
If you will write
char **buf = NULL;
size_t buf_size = 0;
ssize_t bytes_read = getline(buf, &buf_size, stdin);
then the function within itself will try to dereference the null pointer buf that results in undefined behavior because it thinks that the so-called "double pointer" points to an object of the type char * that the function needs to change.
To make it more clear consider the following demonstration programs.
#include <stdio.h>
void f( char *s )
{
s = "World!";
}
int main( void )
{
char *s = "Hello";
printf( "Before calling f s = %s\n", s );
f( s );
printf( "After calling f s = %s\n", s );
}
The program output is
Before calling f s = Hello
After calling f s = Hello
The pointer s passed to the function be value. That is the function deals with a copy of the value of the pointer. Changing the copy does not influence on the original value of the pointer s.
Now consider the next program
#include <stdio.h>
void f( char **s )
{
*s = "World!";
}
int main( void )
{
char *s = "Hello";
printf( "Before calling f s = %s\n", s );
f( &s );
printf( "After calling f s = %s\n", s );
}
The program output is
Before calling f s = Hello
After calling f s = World!
That is as the pointer s is passed to the function by reference the function can change the original pointer s by dereferencing the pointer passed to the function that points to the original pointer s.
As for this declaration
char **name = "John Doe";
then the compiler should issue a message that declaration is wrong. The string literal used as an initializer is implicitly converted tp pointer to its first element of the type char *. But the initialized variable has the type char ** and there is no implicit conversion between these pointer types.
Also the conversion specifier %s expects an argument of the type char * instead of the type char **.
So you have to write
char *name = "John Doe";
Or as you may not change a string literal then it will be better to write the declaration like
const char *name = "John Doe";
In the char *buf case, getline will go to the memory location of the pointer buf and change that address.
In case of char **buf = NULL;, getline will go the memory location "null" and try to change that address, which is nonsense. You essentially lie to getline and tell it that you stored a pointer for it at memory location "null".
As for char **name = "John Doe"; it is a constraint violation of C's assignment rules, anything can happen since the code isn't valid C. Including "seems to work fine all the way until the mysterious crash some years later in live production code". You might want to take the skunk out of that online compiler by for example applying What compiler options are recommended for beginners learning C?
A double pointer has to reference a valid pointer to work (as that pointer will store the reference to the newly allocated memory.
int main(int ac, char **av)
{
printf("Write something: \n");
char *realBuf = NULL
char **buf = &realBuf;
size_t buf_size = 0;
ssize_t bytes_read = getline(buf, &buf_size, stdin);
if (bytes_read != -1)
write(STDOUT_FILENO, *buf, buf_size);
else
printf("An error occured\n");
free(*buf);
return (0);
}
There are no “double pointers” in C, so you cannot use them.
But for any type T, you can create a type “pointer to T”. And that’s the case if T is a pointer type as well. That’s a pointer to a pointer. Not a “double pointer”. If you see char** as a “double pointer” you will forever be confused.
#include <stdio.h>
#include <stdlib.h>
char wordsum(char FW[256],char SW[256]){
int i;
int j=strlen(FW);
for (i=0;i<=strlen(SW);i++)
FW[i+j+1]=SW[i];
printf("%c",FW);
return FW;
}
int main()
{
char F[256];
char S[256];
printf("Enter the first word\n");
gets(F);
printf("Enter the Second word\n");
gets(S);
wordsum(F,S);
return 0;
}
I don't know what is wrong with my code to make strcat function. I hope to find the answer.
I assume that the code is written to learn more about the C language. If so, may I present an alternative implementation which does not use strlen(). The intention is to present some of the really nice features in the language. It may be a bit complicated to wrap ones head around the first time, but IIRC the code can be found in K&R's book The C Programming Language.
Here we go:
char* mystrcat(char *dest, const char *src)
{
char *ret = dest;
while (*dest)
dest++;
while ((*dest++ = *src++))
;
return ret;
}
The first while-loop finds the end of the destination string. The second while-loop appends the source string to the destination string. Finally, we return a pointer to the original dest buffer.
The function could've been even nicer if it didn't return a pointer.
void mystrcat(char *dest, const char *src)
{
while (*dest)
dest++;
while ((*dest++ = *src++))
;
}
HTH
There are several mistakes in your code. They are:
1) A function can't return an array in C and you don't need to do so. Change the return type from char to void of wordsum and erase the line return FW;
2) You want to print a string, right? Format specifier for string is %s. So write printf("%s",FW); instead of printf("%c",FW);.
3) Do this: FW[i+j]=SW[i];. Why did you add an extra 1 to i+j? Just think logically.
4) Add header file for strlen(), it's <string.h>.
5) Erase those asterisk marks before and after FW[i+j]=SW[i];.
There are a few problems in your function, I've changed and commented them below:
char *wordsum(char FW[256],char SW[256]){ // correct function type
int i;
int j=strlen(FW);
for (i = 0; i <= strlen(SW); i++)
FW[i+j] = SW[i]; //change 'i + j + 1' to 'i + j'
printf("%s",FW); //change format specifier as you are printing string not character
return FW;
}
Then dot forget to capture the returned pointer using a char* variable in the calling function (here main())
char *result;
result = wordsum(F,S);
printf("\n%s\n", result);
Working example: https://ideone.com/ERlFPE
I'm trying to store a string with a first and last name from a string into a struct but I'm getting (warning: passing argument 1 of strcpy makes pointer from integer without a cast), and I'm not sure on where to put strcpy tried putting it in the while loop got the error which makes sense. But not sure on where to place strcpy
EDITED
struct trip
{
char first_name;
char last_name;
}
int main(void)
{
struct trip travel[12];
}
char input_name(struct trip travel[MAXTRIP], int index)
{
int name_read, length;
int name_bytes = 100;
char *name, *word;
getchar();
printf("Please enter name:\n");
name = (char *)malloc(name_bytes + 1);
name_read = getline (&name, &name_bytes, stdin);
word = strtok(name, ",");
while (word != NULL)
{
strcpy(travel[index].first_name, word);
word = strtok(NULL, ",");
}
}
Ignoring the (MANY) errors in your code, you are putting the strcpy() in the right place.
However, you are not calling it with the correct arguments: strcpy() needs 2 arguments.
Basically, both are of type char*; you are passing a char and a char* and that is why the compiler complains (for the compiler the char behaves like an int so it says "strcpy makes pointer from integer").
You need to review your data structure and pass the right char*s to strcpy().
Can anyone explain why I am getting segmentation fault in the following example?
#include <stdio.h>
#include <string.h>
int main(void) {
char *hello = "Hello World, Let me live.";
char *tokens[50];
strtok_r(hello, " ,", tokens);
int i = 0;
while(i < 5) {
printf("%s\n", tokens[i++]);
}
}
Try this:
#include <stdio.h>
#include <string.h>
int main(void) {
char hello[] = "Hello World, Let me live."; // make this a char array not a pointer to literal.
char *rest; // to point to the rest of the string after token extraction.
char *token; // to point to the actual token returned.
char *ptr = hello; // make q point to start of hello.
// loop till strtok_r returns NULL.
while(token = strtok_r(ptr, " ,", &rest)) {
printf("%s\n", token); // print the token returned.
ptr = rest; // rest contains the left over part..assign it to ptr...and start tokenizing again.
}
}
/*
Output:
Hello
World
Let
me
live.
*/
You need to call strtok_r in a loop. The first time you give it the string to be tokenized, then you give it NULL as the first parameter.
strtok_r takes a char ** as the third parameter. tokens is an array of 50 char * values. When you pass tokens to strtok_r(), what gets passed is a char ** value that points to the first element of that array. This is okay, but you are wasting 49 of the values that are not used at all. You should have char *last; and use &last as the third parameter to strtok_r().
strtok_r() modifies its first argument, so you can't pass it something that can't be modified. String literals in C are read-only, so you need something that can be modified: char hello[] = "Hello World, Let me live."; for example.
A bunch of things wrong:
hello points to a string literal, which must be treated as immutable. (It could live in read-only memory.) Since strtok_r mutates its argument string, you can't use hello with it.
You call strtok_r only once and don't initialize your tokens array to point to anything.
Try this:
#include <stdio.h>
#include <string.h>
int main(void) {
char hello[] = "Hello World, Let me live.";
char *p = hello;
char *tokens[50];
int i = 0;
while (i < 50) {
tokens[i] = strtok_r(p, " ,", &p);
if (tokens[i] == NULL) {
break;
}
i++;
}
i = 0;
while (i < 5) {
printf("%s\n", tokens[i++]);
}
return 0;
}
strtok_r tries to write null characters into hello (which is illegal because it is a const string)
You have understood the usage of strtok_r incorrectly. Please check this example and documentation
And try & see this:
#include <stdio.h>
#include <string.h>
int main(void)
{
char hello[] = "Hello World, let me live.";
char *tmp;
char *token = NULL;
for(token = strtok_r(hello, ", ", &tmp);
token != NULL;
token = strtok_r(NULL, ", ", &tmp))
{
printf("%s\n", token);
}
return 0;
}
I think it might be the char *tokens[50]; because you are declaring it a pointer when it is already a pointer. An array is already a pointer upon declaration. You mean to say char tokens[50];. That should do the trick.