Tokenizing a string in C - c

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().

Related

Setting return value of char pointer to a char array

Trying to learn C. To that end, I'm coding a program that creates a TroubleTicket report. The user is prompted to enter, priority, name and problem. I'm using a struct to store the data and create a struck array. Using the array approach for now as I'm developing the code. Eventually, I'd to use a linked list.
Anyhow, the get_input() function reads in the user input and returns a char pointer.
Included the get_input() and create_ticket() functions.
#define NUM_TICKETS 10
char* get_input(int maxlen)
{
static char s[110];
char ch;
int i = 0;
int chars_remain = 1;
while (chars_remain)
{
ch = getchar();
if ((ch == '\n') || (ch == EOF))
{
chars_remain = 0;
}
else if (i < maxlen - 1)
{
s[i] = ch;
i++;
}
}
s[i] = '\0';
return s;
void create_ticket()
{
struct ticket
{
int priority;
int number;
char * name;
char * problem ;
char * assigned_to;
char * status ;
};
struct ticket tkt_array[NUM_TICKETS];
struct ticket new_ticket;
printf("Enter your name: ");
new_ticket.name = get_input(20);
printf("new_ticket.name: %s \n", new_ticket.name);
printf("Enter problem description: ");
new_ticket.problem = get_input(100);
printf("new_ticket.problem: %s \n", new_ticket.problem);
printf("Assigned to: ");
new_ticket.assigned_to = get_input(20);
printf("new_ticket.assigned_to %s\n ", new_ticket.assigned_to);
printf("Enter ticket status: ");
new_ticket.status = get_input(10);
printf("new_ticket.status: %s \n", new_ticket.status);
}
I noticed that initial input was read and displayed correctly but subsequent inputs overwrote prior input.
For example, after name was entered, the entered value is displayed
printf("Enter your name: ");
new_ticket.name = get_input(20);
printf("new_ticket.name: %s \n", new_ticket.name);
But after problem description is entered, new_ticket.name was changed to display the problem description text. Took me a while to figure out that the problem is the return s in get_char(). It returns a pointer. The address is the same but the value changes and struct ticket pointers point to the same address of return s from get_char().
How can I save the return value in a variable and not get it reset on subsequent call to get_input?
s is a char *, how can I save the return value of a pointer in a variable?
printf("Enter problem description: ");
new_ticket.problem = get_input(100);
printf("new_ticket.problem: %s \n", new_ticket.problem);
printf("new_ticket.name: %s \n", new_ticket.name);
How can I save the return value in a variable and not get it reset on subsequent call to get_input?
s is a char *, how can I save the return value of a pointer in a variable?
I hope I clearly stated the issue.
This answer addresses only the problem stated in the question, not other errors or problems in your code.
Your function get_input uses a single array static char s[110]; to store the input and always returns the address of this array.
Assignments like new_ticket.name = get_input(20); will store the same address in all pointer variables, so all will actually point to the same variable s which will contain the last input.
One option to solve this would be to replace the pointers in your structure with arrays and either pass this to get_input or copy the value using strcpy.
Or you could use the (non-standard) function strdup to get a dynamically allocated duplicate of the input string. If this function is not available, you could implement it using malloc and strcpy.
Example:
new_ticket.name = strdup(get_input(20));
Note: When using strdup, you should free the memory when it's no longer needed.
or using a replacement for strdup:
const char *s1;
char *s2;
/* ... */
s1 = get_input(20);
s2 = malloc(strlen(s1) + 1);
if(s2 == NULL)
{
/* handle error */
}
else
{
strcpy(s2, s1);
}
new_ticket.name = s2;
(You could implement your own function that wraps malloc and strcpy.)
or with arrays instead of pointers as structure fields
struct ticket
{
int priority;
int number;
char name[20];
char problem[100];
char assigned_to[20];
char status[10];
};
/* ... */
strcpy(new_ticket.name, get_input(sizeof(new_ticket.name));
The static keyword creates a value that exists once, so multiple invocations of the function point to the same data.
If you want to dynamically create data with a lifetime that you control, you may allocate your own memory.
malloc(size) will allocate a block of memory with the size provided. This memory will exist and be valid until you call free on that memory.
You should be careful though, calling free twice, or forgetting to call it at all, are common sources of bugs within c code.
The other option in this is to have the caller of the function provide the memory. You could change your struct ticket to have char name[MAX_NAME_LEN], and update the function get input to get_input(int max_len, char * buffer). This also solves the problem, while avoiding potentially erroneous malloc and frees.

How to assign a string to struct variable in C?

I am unable to figure out how to assign a string to a struct variable using only <stdio.h> header file.
The following code gives me an error and I am unable to fix it.
#include <stdio.h>
struct Student
{
char name[50];
};
int main()
{
struct Student s1;
printf("Enter studen's name:\n");
scanf("%s",s1.name);
printf("Name : \n",s1.name);
s1.name={"Hussain"};
printf("Name : \n",s1.name);
}
It gives the following error while compilation:
test.c: In function 'main':
test.c:12:12: error: expected expression before '{' token
s1.name={"Hussain"};
^
I have tried initializing it in the following way:
s1.name="Hussain";
But this doesn't work too.
I could avoid this by the use of pointers as follows:
#include <stdio.h>
struct Student
{
char *name;
};
int main()
{
struct Student s1;
printf("Enter studen's name:\n");
scanf("%s",s1.name);
printf("Name : %s\n",s1.name);
s1.name="Hussain";
printf("Name : %s\n",s1.name);
}
This code works perfectly fine with no errors.
But I want to know where exactly I am doing wrong with the array, which is making my code not work.
A char array (and arrays in general) can't be assigned a value directly, only initialized. To write a string into a char array, use strcpy.
strcpy(s1.name, "Hussain");
The latter code where the name member is a pointer works for the assignment because the pointer is assigned the start address of the start of the string constant. Also note that you can't (at least not yet) use strcpy in that case because s1.name doesn't point anywhere. You would first need to allocate memory using malloc, or perform both steps at once using strdup. Also for this reason, you can't yet use scanf until you allocate memory.
If you're not allowed to use functions from string.h, then you would need to write the characters into the array one at a time, and then write a terminating null byte at the end.
Arrays do not have the assignment operator. So these assignment statements
s1.name = { "Hussain" };
s1.name = "Hussain";
are invalid.
You could use the standard C string function strcpy to copy elements of the string literal to the array s1.name like
#include <string.h>
//...
strcpy( s1.name, "Hussain" );
If you may not use standard string functions then you need to write a loop as for example
const char *p = "Hussain";
for ( char *t = s1.name; ( *t++ = *p++ ) != '\0'; );
Or
for ( char *t = s1.name, *p = "Hussain"; ( *t++ = *p++ ) != '\0'; );
Pay attention to that the second your program has undefined behavior. The pointer s1.name is not initialized and does not point to a valid object of an array type. So the call of scanf in this code snippet invokes undefined behavior.
struct Student s1;
printf("Enter studen's name:\n");
scanf("%s",s1.name);
If you can't use <string.h>, then you have to implement your own version of strcpy():
void copystring(char *dest, const char *src)
{
const char *p = src;
while (*p) {
*dest = *p;
p++;
dest++;
}
*dest = '\0'; // Null-terminate string (as pointed by #Ted)
}
Make sure that dest has enough space to hold src.
Also, avoid using scanf() in your code. Use fgets() as an alternative.
EDIT: As pointed by Jabberwocky, fgets() leaves \n read in the string. But since using <string.h> is not allowed, you have to implement your own function to replace it with a null-terminator:
int findchar(const char *str, char c)
{
int pos;
for (pos = 0; str[pos]; ++pos)
if (str[pos] == c)
return pos;
return -1;
}
You can use it like:
char str[100];
if (!fgets(str, sizeof str, stdin)) {
// fgets() failed. Do something.
} else {
int nwln = findchar(str, '\n');
if (nwln == -1) {
// You probably entered more than 100 characters
// because \n couldn't be found.
} else {
str[nwln] = '\0';
}
}

Access char sequence in arrays of char pointers

I have a problem with assigning specific pointer to another char sequence(string);
#include<stdio.h>
void setInformations(char *informations[], char *contests_name[]);
int main(void) {
char *informations[]={"","","",""};
char *contests_name[]={"cycle_race","swim","running race"};
int totalTime=0;
setInformations(informations,contests_name);
getch();
return 0;
}
void setInformations(char *informations[], char *contests_name[]) {
printf("Competitor's name: ");
scanf("%s",*informations[0]);
printf("%s",informations[0]);
}
I know that the problem is assigning string to pointer of type char. How can I replace this (strcpy?)
Take the * out of the scanf:
scanf ("%s", informations[0]);
...and allocate space for the informations array
char* informations[NUMBER_OF_INFORMATIONS][MAX_NAME_LENGTH] = {{'\0'}};
so scanf will have room to put in the info.
here : scanf("%s",*informations[0]);, you are trying to write in a read-only memory.
So you have to allocate the memory in the main :
int stringSize = 30; // example of length
char* informations[3];
informations[0] = malloc(stringSize);
informations[1] = malloc(stringSize);
informations[2] = malloc(stringSize);
//initialyse the strings to "" :
informations[0][0] = '\0';
informations[1][0] ='\0';
informations[2][0] ='\0';
in setInformations(, you have to delete the * to give scanf the adress of the memory where to write). correct syntax : scanf("%s",informations[0]);

C simple string program does not compile

#include <stdio.h>
#include <string.h>
char Jones(char, char);
int main() {
char name[]="Andrew";
char surname[]="Jones";
char result[80];
result=Jones(name, surname);
puts(result);
return 0;
}
char Jones(char name, char surname)
{
char result[80];
int length;
length = strlen(surname);
for (int i=0; i<50; i++)
{
result[length+i] = name[i];
}
return result;
}
The program does not compile and i dont know why. It is supposed to read two strings and swap their places. It should display eg. "Jones Andrew".
Here's one problem:
char name[]="Andrew";
char surname[]="Jones";
char result[80];
wynik=Jones(name, surname);
This calls Jones() with character arrays (which will decay to character pointers), but the function is declared to accept single characters only.
You should change the function to take char *name, char *surname, since it really does seem to expect strings.
Further, you can't return a character array like you're doing in Jones(), you need to read up quite a bit on how to work with strings in C.
Also, wynik looks undeclared, that'll also make it fail to build.
There's a few errors:
char Jones(char, char);
This takes just a single char, not a char * which you need for a string.
result=Jones(name, surname);
Here result is an array. In C, you cannot assign to an array.
char Jones(char name, char surname)
{ char result[80];
...
return result;
}
Here you return result which is a local variable. But to return a string, you'd need to return a char*. But that char* would point to a local variable within the Jones function, which is no longer valid when the function ends. One solution is to pass in a buffer where you write the result that the caller owns.
Your algorithm for combining the surename and name is also wrong, you never do anything with the surename.
You'll need to do this:
char *Jones(char*, char* , char *);
int main() {
char name[]="Andrew";
char surname[]="Jones";
char result[80];
char *p;
p = Jones(name, surname, result);
puts(p);
return 0;
}
char *Jones(char *name, char *surname, char *result)
{
int length;
int i,k;
length = strlen(surname);
for (i=0; i<length ; i++)
{
result[i] = surname[i];
}
result[i++] = ' '; //add a space
length = strlen(name);
for (k=0; k<length ; k++, i++)
{
result[i] = name[k];
}
result[i] = 0; //add nul terminator to end the string
return result;
}
The conatenation could be simplified in many ways, e.g. to
strcpy(result, surename);
strcat(result, " ");
strcat(result, name);
or the Jones function could just do:
sprintf(result, "%s %s", surename, name);
In all cases, the function is rather fragile, as it's easy to overflow the result buffer if you pass in something else that does not fit within the result buffer.
1) The name and surname are char array and not single char so you have to change the input parameters types of your function Jones() the input parameters types should be char name[] (char array) or char *name (pointer to array of char)
2) You can not return an array defined locally and statically in the function. and if you want to return a string from the function, the string should be constant or it should be a buffer allocated dynamically (with malloc, calloc, realloc) into the function And for both cases the function type should be char *Jonas() and not char Jonas()
Or you can pass the result array via input parametr. and in this case you can fill it into the function.
void Jones(char *name, char *surname, char *result)
and in the main:
char result[80];
Jones(names, surname, result);
3) The following for loop is missing some thing
for (int i=0; i<50; i++)
{
result[length+i] = name[i];
}
The result elements from element 0 to element length are containing garbage because the result array is not initiated. so when you printf the result array you will get garbages printed. You have to initiate elements between 0 to length in the result array
#include <stdio.h>
#include <string.h>
char* Jones(char*, char*);
int main() {
char name[]="Andrew";
char surname[]="Jones";
puts(Jones(name,surname));
return 0;
}
char* Jones(char *name, char *surname)
{
strcat(surname," ");
strcat(surname,name);
return surname;
}

strtok - how avoid new line to and put to array of strings?

if i dupe topic i really sorry, i searched for it with no result here.
I have code
void split(char* str, char* splitstr)
{
char* p;
char splitbuf[32];
int i=0;
p = strtok(str,",");
while(p!= NULL)
{
printf("%s", p);
sprintf(&splitstr[i],"%s",p);
i++;
p = strtok (NULL, ",");
}
}
How can i use proper sprintf to put the splited words by strtok to string array?
Can i somehow avoid breaklines created by strtok?
I am programming in ANSI C. I declared array splitstr and str the same way.
char* splitstr;//in main char splitstr[32];
Thanks for help.
edit:
i would like do something like this:
INPUT (it is a string) > "aa,bbb,ccc,ddd"
I declare: char tab[33];
OUTPUT (save all items to array of strings if it is even possible) >
tab[0] is "aa"
tab[1] is "bbb"
...
tab[3] is "ddd" but not "ddd(newline)"
edit2 [18:16]
I forgot add that the data string is from reading line of file. That's why i wrote about "ddd(newline)". I found after that the new line was also shown by strtok but as another item. By the way all answers are good to think over the problem. Few seconds ago my laptop has Broken (i dont know why the screen gone black) As soon as i take control over my pc i will check codes. :-)
Give this a shot:
#include <stdlib.h>
#include <string.h>
...
void split(char *str, char **splitstr)
{
char *p;
int i=0;
p = strtok(str,",");
while(p!= NULL)
{
printf("%s", p);
splitsr[i] = malloc(strlen(p) + 1);
if (splitstr[i])
strcpy(splitstr[i], p);
i++;
p = strtok (NULL, ",");
}
}
And then, in main:
#define MAX_LEN ... // max allowed length of input string, including 0 terminator
#define MAX_STR ... // max allowed number of substrings in input string
int main(void)
{
char input[MAX_LEN];
char *strs[MAX_STR] = {NULL};
...
split(input, strs);
...
}
Some explanations.
strs is defined in main as an array of pointer to char. Each array element will point to a string extracted from the input string. In main, all that's allocated is the array of pointers, with each element initially NULL; the memory for each element will be allocated within the split function using malloc, based on the length of the substring. Somewhere after you are finished with strs you will need to deallocate those pointers using free:
for (i = 0; i < MAX_STR; i++)
free(strs[i]);
Now, why is splitstr declared as char ** instead of char *[MAX_STR]? Except when it is the operand of the sizeof or & operators, or is a string literal being used to initialize another array in a declaration, an array expression will have its type implicitly converted from N-element array of T to pointer to T, and the value of the expression will be the location of the first element in the array.
When we call split:
split(input, strs);
the array expression input is implicitly converted from type char [MAX_LENGTH] to char * (T == char), and the array expression strs is implicitly converted from type char *[MAX_STRS] to char ** (T == char *). So splitstr receives pointer values for the two parameters, as opposed to array values.
If I understand correctly, you want to save the strings obtained by strtok. In that case you'll want to declare splitstr as char[MAX_LINES][32] and use strcpy, something like this:
strcpy(splitstr[i], p);
where i is the ith string read using strtok.
Note that I'm no ansi C expert, more C++ expert, but here's working code. It uses a fixed size array, which may or may not be an issue. To do anything else would require more complicated memory management:
/* Not sure about the declaration of splitstr here, and whether there's a better way.
char** isn't sufficient. */
int split(char* str, char splitstr[256][32])
{
char* p;
int i=0;
p = strtok(str,",");
while(p) {
strcpy(splitstr[i++], p);
p = strtok (NULL, ",");
}
return i;
}
int main(int argc, char* argv[])
{
char input[256];
char result[256][32];
strcpy(input, "aa,bbb,ccc,ddd");
int count = split(input, result);
for (int i=0; i<count; i++) {
printf("%s\n", result[i]);
}
printf("the end\n");
}
Note that I supply "aa,bbb,ccc,ddd" in and I get {"aa", "bbb", "ccc", "ddd" } out. No newlines on the result.

Resources