i want to make a strncpy function so i try to make it but i can't.
i made a struct. struct have int age ; and char name[20]. so i want to name[20] copy strings which from scanf. but it fail... how can i make a
strlcpy function?
(*list).name++ = name++;
is error... if this is work, i can make a strncpy.
void makeUserList (Unit* list, const char *name, int age ){
while (*name) {
NSLog(#"%c",*name);
(*list).name++ = name++;
// (list->name)++ = name++;
NSLog(#"%c",*list[roomNum].name);
}
i'm from korea. please understand my english grammar...
Have a nice daY~
First of all, the code (*list).name++ = name++; will copy only one character. It should be repeated for the whole length of name. Second: This code will modify the list's name field as well, such that it will point to the end of the copied string, which is obviously not what you want. If you want this to work, you should copy the destination pointer and work with this copy. Look here for example.
Related
C function to remove the first string from an XOR linked list of names:
int remove_string(Node **head, char *deleted_string) {
Node *temp = *head;
*deleted_string = *(*head)->name;
*head = calculate_xor_value(NULL, temp->xor_value);
if (*head != NULL) {
(*head)->xor_value = calculate_xor_value(NULL, calculate_xor_value(temp, (*head)->xor_value));
}
free(temp);
}
In the question, one of the input parameters has to be a char pointer called deleted_string, which is the string that is being removed from the list. The code to remove the string works fine (line 4 onwards), but I am struggling to save the string to the char* deleted_string (line 3) *deleted_string = *(*head)->name;
Everytime I run the code
// printf("%s", deleted_string ); only the first character is being printed; I think I understand that this is because pointers only point to the first character of a string, but is there a way to make the pointer point to the whole string? Perhaps by somehow converting (*head)->name to a string or an array?
Any help would be appreciated, sorry if this is a silly question. I have spent hours trying to find another page about this but I didn't so I thought I'd ask.
Assuming (*head)->name is of type char*, you are dereferencing both the char *deleted_string and char *name, hence operating on something of type char.
The line
*deleted_string = *(*head)->name;
is equivalent of doing something like
char a;
char b = 0;
a = b;
If you want to copy the contents of (*head)->name into the deleted_string, you can use strcpy or strncpy like,
strncpy( deleted_string, (*head)->name, SIZE );
Where the SIZE is whatever maximum size the deleted_string can hold. strcpy is the same, just without the size argument.
As comments suggested, both should be used with care, as strcpy can attempt to copy more characters than the destination can hold, causing write violations, and strncpy will truncate if the source is bigger than the destination, the resulting string will not necessarily be null-terminated. In such case, functions that assume the string is null-terminated will misbehave, such as printf( "%s" ... ), causing read violations. For more information, you can check this post.
Let's say we have this struct
struct Foo{
int FooLength; //length of Foo
char FooChar[4];
};
and then in the main we have
int sizeFoo = 100; struct Foo myFooList[sizeFoo];
what would be the best way to input data for FooChar? Would strncpy, or memcpy, or snprintf, or sprintf?
what I wish to do is something like
myFooList[0].FooLength = 3;
myFooList[0].FooChar = "dog";
myFooList[1].FooLength = 3;
myFooList[1].FooChar = "cat";
.
.
.
with a correct syntax since in C you can't just = "string"; here, and I'm not sure what would be the best way to go about it? I have look at similar topics, but I just get more confused with how strncpy or sprintf are not good or you have to have a \0 added at the end or some other detail that makes picking what to do more difficult.
Also if all the values of myFooList[] are already know (they are const or static) is there a way to initialize like one would do any other array?
If your input is always 3 characters, you can use strcpy, otherwise use strncpy(myFooList[0].FooChar, "dog", 3). You must add the terminating null character if using strncpy. strcpy will add the termination null character automatically, just like VHS has in his answer. In either case, you should still validate that your input does not exceed the maximum length. To find the length of a string(i.e. the number of char characters up to the first null character), you would use strlen. To determine the capacity of a char a[], you can use _countof(a). Don't forget that one of those has to be a '\0'.
memcpy would also work, but it would be unusual to do that with a string.
You wouldn't use sprintf here. sprintf would normally be used when you need to create a unique string using dynamic data at runtime. This is not what you're doing here. If you have any experience with .NET, it is the C equivalent of string.Format.
To initialize an array of 'Foo', you will just need to write a function that will do that. Even if you figure out the syntax to do it in one line, it'll be very difficult to read and maintain. Here's an example without validation, I will leave that task to you.
myFooList[0].FooLength = 3;
strncpy(myFooList[0].FooChar, "dog", 3);
myFooList[0].FooChar[3] = '\0';
myFooList[1].FooLength = 3;
strncpy(myFooList[1].FooChar, "cat", 3);
myFooList[1].FooChar[3] = '\0';
Your integer assignment is correct, but the string assignment is not. Following is the right way:
myFooList[0].FooLength = 3;
strcpy( myFooList[0].FooChar, "dog");
myFooList[1].FooLength = 3;
strcpy(myFooList[1].FooChar, "cat");
what would be the best way to input data for FooChar? Would strncpy,
or memcpy, or snprintf, or sprintf? ...
but I just get more confused with how strncpy or sprintf are not good
or you have to have a \0 added at the end or some other detail that
makes picking what to do more difficult.
Well, memcpy is a good choice if you don't want terminate nul byte. I don't really understand what is your question here.
Also if all the values of myFooList[] are already know (they are const
or static) is there a way to initialize like one would do any other
array?
In your example, no, because you use VLA who can't be initialize. But you could do the following:
#include <stdio.h>
struct Foo {
int FooLength; // length of Foo
char FooChar[4];
};
int main(void) {
struct Foo myFooList[] = {{3, "dog"}, {3, "cat"}};
size_t size = sizeof myFooList / sizeof *myFooList;
}
I want to copy the content of some char-arrays passed as parameters in a function to another char-arrays. So I passed these arrays as pointers (passing by reference). Then I used memcpy to copy the content of these arrays to some other arrays. But the copying-process was not too exact, although I think that I used memcpy correctly. Some characters was deleted, while some new charcters appeared. I tried then to use strcpy, so the content of these arrays was correctly copied. So I want to understand why copying process failed when using memcpy. Here is the some of my code:
struct student{
bool statusFlag;
char lastname[20];
char firstname[20];
int mNr;
};
here is the method:
struct student getData(char * lastname, char * firstname, int matNr){
struct student st;
int i;
printf("%s\n",lastname);
if(insertCounter<=size){
//get data
st.statusFlag=1;
memcpy(st.lastname,lastname,strlen(lastname));
memcpy(st.firstname,firstname,strlen(firstname));
st.mNr=matNr;
printf("%s,%s,%d\n",st.lastname,st.firstname,st.mNr);
return st;
}else if(insertCounter>size){
st.statusFlag=0;
return st;
}
When I replaced memcpy with strcpy, The copy-operation was successful:
The statement
memcpy(target,source, strlen(source))
should copy all the chars of the string. But, it will stop just short of copying the 0-byte that marks the end of the string. So what you copied won't be a string. This will be a problem if you call any string functions on the new copy (target), basicaly if you use target in any way, you will march off the end, since the end is now unmarked. Probably you will pick up some extra bytes, anything that happens to be in memory after target, worst case you program segfalts if it marches far enough without finding a 0. The function strcpy will copy the 0-byte, I usually use
snprintf(target, sizeof target, "%s", source);
Since it does not write past the end of the target buffer, and it always makes room for the 0, protecting against trouble in the next string op.
I have created a C program where I'm supposed to read a text file and assign it to a structure through int and string pointers.
Here's a code snippet of my program:
i = 0;
while(!feof(phoneBook)) {
fscanf(phoneBook, "%d|%s\n", &num, fname);
info[i].phone_num = num;
printf("%d\n", info[i].phone_num);
info[i].first_name = fname;
printf("%s\n", info[i].first_name);
i++;
ctr++;
printf("\nfirst:%s", info[0].first_name);
printf("\nsecond:%s", info[1].first_name);
printf("\nthird:%s\n\n", info[2].first_name);
}
On the first iteration, it assigns the first line to the 0 index of info.
For the second iteration, it assigns the second line to index 1 AND replaces index 0.
The text file only contains the following lines (for testing purposes):
first
second
third
Here's the output:
//first iteration
first:first
second: <null>
third: <null>
//second
first:second
second: second
third: <null>
//third
first:third
second: third
third: third
By the way, I declared my structure as:
typedef struct{
int id;
char *first_name;
char *last_name;
int phone_num;
} phone_det;
where phoneBook was declared under the datatype phone_det.
Any form of help would be greatly appreciated! I just started using C and I can still get a little confused with pointers. :(
Although we, can't see your structure, you assign the pointer to the same name buffer each time, and don't copy the name buffer itself to the specific array, so you end up with many different pointers to the same name buffer.
The problem is the assignment info[i].first_name = fname;. This does not make a copy of the string - it simply sets info[i].first_name to point to the same memory that fname points to. So after each iteration, they all point to the same memory that fname points to. Thus, when you fscanf a new value into the buffer, all of the structs see the new contents.
Your assigning info[i].first_name to point to fname; Instead of declaring fname as: char* fname; (as I'm assuming you did), do something like this: char[MAX_SIZE] fname; and then use strcpy to copy over the value. So do: strcpy(info[i].first_name, fname);
This is a guess because I can't see all your code, but I bet you just have char * for these items, that is you are assigning the pointers to a string.
fname is actually a buffer. (maybe a char fname[20]) so each item is pointing to fname which changes with each read.
To fix this problem make the structure contain an array. Then use strcpy or strncpy to copy it from fname.
You should copy the name, rather than point to it. You are setting all your pointer to the location that you read the last name into. Use strcpy or some such.
Or, to make life even simpler, make sure that the first_name element was assigned sufficient space, then read directly into it with
fscanf(phoneBook, "%d|%s\n", &(info[i].phone_num), info[i].first_name);
Each iteration reads into fname, and then assign's fname's address to info[i].first_name. fname's address doesn't change between each iteration, so you're assigning the same address to all of the first_name pointers!
You'll want to allocate an unique array for each iteration so that the strings are stored in different locations, rather than each one overwriting the last.
while(!feof(phoneBook)) {
char *fname = malloc(SUITABLY_LARGE_SIZE);
if (fname == NULL) {
perror("malloc");
exit(1);
}
fscanf(phoneBook, "%d|%s\n", &num, fname);
info[i].first_name = fname;
...
}
I have this structure of Node
typedef struct Node{
unsigned int length;
char *string;
} Node;
And this operation which accepts a pointer to a Node and tries to attach the provided string:
int setString(Node *node, char *string){
char *newString;
if(!isString(node) || !string) return 0;
newString = (char *) malloc(strlen(string)+1);
if(!newString) return 0;
/*THIS PART FAILS*/
strncpy(newString,string,sizeof(newString));
node->string = newString;
node->length = strlen(newString);
/*Which can be seen here*/
printf("Original String: %s\n",string);
printf("Copied String: %s\n",node->string);
return 1;
}
At the indicated part, I can see that the original string doesn't seem be copied over to node->string. It copies over the first two characters, and then what follows is either garbage or just blank.
I checked this post and I am following the third case, which seems to work for the OP. Maybe I overlooked something, but just can't figure out where
strncpy(newString,string,sizeof(newString));
In this context sizeof doesn't do what you want. Pass the size you allocated or don't use strncpy. If you follow your own logic, you already trust string since you took its strlen when you called malloc.
So you can safely use strcpy instead.
If you're willing to go a little non-portable, you could get away with:
newString = strdup(string);
Your sizeof() call is causing your problem:
sizeof(newString);
newString is a pointer to a character is declared here:
char *newString;
And character pointers use (normally) 2,4 or 8 bytes (depending on the machines architecture).
So it's clear, that you are only copy the first 2/4/8 bytes. Use strlen(string) + 1 for the number of characters to copy.
Or you can just use strcpy(). This will take care of the terminating null byte. Since you are calling malloc() correctly with strlen there is no chance to cause a overflow with strcpy().
You can not use the sizeof() in order to determine the string length.
You have to use the strlen(string) function instead.
Also you need to set \0 after copied symbols to terminate the string.
Not sure, but try directly this:
strncpy(node->string,string,strlen(newString));
Changing the length function to strlen.
(i tried to make the changes in code to bold)