character array filling - c

I want to declare character array and later want to fill it. But getting error:
char line[BUFSIZE+1];
strcpy(line,"Memory is Full", sizeof(line));
Error is:
wrong number of arguments in call to strcpy.
Is there any alternative to achive this?

If you have it, use strlcpy(). It does what you might expect strncpy() to do.
Failing that, I would recommend using snprintf(), if you have it.

strcpy() takes 2 arguments, strncpy() takes 3.
I think you were thinking about using strncpy, that takes destination, source, and size.
ie:
int main()
{
char i[6];
strncpy(i, "Hello", sizeof(i));
printf("%s\n", i);
return 0;
}
>> ./a.out
>> Hello
Note: You have to append the '\0' yourself if you completly fill your char[], otherwise strncpy() will do it for you (as in my example).

strcpy doesn't take a size/length argument. Use memcpy instead, but give it the size (length+1) of the string being copied, not the size of the buffer, or you risk undefined behavior/segfaults.

Related

How can i copy part of a string to another variable?

Hi i am trying to figure out how to copy only part of a line being read from a text file. I want to copy a line from a file called fileLine to a variable called line. The problem is, is that i only want to copy starting at index 10 in fileLine but memcpy dislikes that. How can i change this to make memcpy happy?
int stringLength = 0;
stringLength = strlen(fileLine);
memcpy(line, fileLine[10], stringLength); //this is where things go wrong.
You have passed in a char type to something that expected a const void*. This would have been okay if you had passed it a char*. You can do that as either &fileLine[10] or fileLine + 10.
Since you are offsetting by 10, you also want to ensure you copy 10 fewer characters:
memcpy(line, &fileLine[10], stringLength-10);
Although you probably want to copy the string terminator too...
memcpy(line, &fileLine[10], stringLength-9);
Yuck!
Instead, you could use strcpy:
strcpy(line, fileLine + 10);
In all cases, make sure that line is an array or a pointer to memory that is actually allocated to your process.
You can use getline function to get part of the string. But first, you have to move your read pointer to the position from which you want to read using seekg function.
seekg(ios flag, bytes);
cin.getline(source, number of characters, ending character);

Getting substring from string in C

I have a string "abcdefg-this-is-a-test" and I want to delete the first 6 characters of the string. This is what I am trying:
char contentSave2[180] = "abcdefg-this-is-a-test";
strncpy(contentSave2, contentSave2+8, 4);
No luck so far, processor gets stuck and resets itself.
Any help will be appreaciated.
Question: How can I trim down a string in C?
////EDIT////
I also tried this:
memcpy(contentSave2, &contentSave2[6], 10);
Doesn't work, same problem.
int len=strlen(content2save);
for(i=6;i<len;i++)
content2save[i-6]=content2save[i];
content2save[i-6]='\0'
This will delete first 6 charcters . Based on requirement you may modify your code. If you want to use an inbuilt function try memmove
The problem with your first code snippet is that it copies the middle four characters to the beginning of the string, and then stops.
Unfortunately, you cannot expand it to cover the entire string, because in that case the source and output buffers would overlap, causing UB:
If the strings overlap, the behavior is undefined.
Overlapping buffers is the problem with your second attempt: memcpy does not allow overlapping buffers, so the behavior is undefined.
If all you need is to remove characters at the beginning of the string, you do not need to copy it at all: simply take the address of the initial character, and use it as your new string:
char *strWithoutPrefix = &contentSave2[8];
For copying of strings from one buffer to another use memcpy:
char middle[5];
memcpy(middle, &contentSave2[8], 4);
middle[4] = '\0'; // "this"
For copying potentially overlapping buffers use memmove:
char contentSave2[180] = "abcdefg-this-is-a-test";
printf("%s\n", contentSave2);
memmove(contentSave2, contentSave2+8, strlen(contentSave2)-8+1);
printf("%s\n", contentSave2);
Demo.
Simply you can use pointer because contentSave2 here is also a pointer to a char array plus this will be quick and short.
char* ptr = contentSave2 + 6;
ptr[0] will be equal to contentSave2[6]
You can use memmove function.
It is specially used when source and destination memory addresses overlap.
Small word of advice, try to avoid copying to and from overlapping source and destination. It is simply a buggen.
The following snippet should works fine:
#include <stdio.h>
#include <string.h>
int main() {
char contentSave2[180] = "abcdefg-this-is-a-test";
strncpy(contentSave2, contentSave2+8, 4);
printf("%s\n", contentSave2);
return 0;
}
I would suggest posting the rest of your code because your issue is elsewhere. As others pointed out, watch out for overlap when you use strncpy though in this specific case it should works.

Segmentation fault while operating on user input string

Hi Im new to coding in C and I can't seem to find the problem which causes a segfault after the while loop starts.
int main() {
char option;
char nickname;
printf("Welcome to our chat program. Please select mode (Send,Nickname,Exit): ");
while (gets(option)) {
if(!strncmp(option, "Exit", 4)) {
break;
}
if(!strncmp(option, "Nickname", 8)){
set_nickname(nickname);
}
if(!strncmp(option, "Send", 4)){
if(!nickname){
nickname = "Anonymous";
printf("Your nickname was set to Anonymous!");
}
send_message(nickname);
}
}
There are many issues with the code. Let's discuss them one by one.
First of all, a char is not sufficient to hold a string, you need either
an array
a pointer with proper (dynamic) memory allocation.
Using the first approach, you need to change
char option;
char nickname;
to
#define SIZ 64
char option[SIZ] = {0};
char nicknamep[SIZ] = {0};
Then, instead of using gets(), you should be using fgets() to avoid the possibility of buffer overflow. Something like
fgets(option, SIZ, stdin);
will do.
That said, once option becomes an array, you cannot assign to it. You need to use strcpy() to copy the content into the array. For example,
strcpy(nickname, "Anonymous");
There is no memory allocated for the strings.
You need someting like this:
char option[50];
char nickname[50];
and use strcpy() here:
nickname = "Anonymous";
and check the string with strlen() for example.
if(!nickname){
It is also safer to use fgets() with a length parameter to prevent buffer overflow.
while (gets(option)) {
option needs to be char[???]
Not sure about nickname but it also needs memory allocated and/or initialisation. How do you set it? What value do you use?
You'll also need to check for strlen(nickname)>0 rather than !nickname which will test for a null pointer, not an empty string.
Never ever use gets; it cannot be used correctly. Instead, use fgets, with stdin as the third parameter.
You will notice that fgets takes the length of the storage you want to assign as its second parameter. The lack of this parameter in the gets function is why it cannot be used correctly. You should pass it the value 1 in your case, and pass it the address of your char variable. fgets will then read one character into your variable.
If you want to read more, you need to start by allocating more storage for the data you'll read. For instance, you could allocate space for 80 characters:
char string[80];
You can now use fgets with string as the first character, 80 as the second, and stdin as the third. fgets will then read up to 80 characters from stdin.
If you don't want to store that number in two locations in your source code, you can use the sizeof operator instead, or use a macro to predefine the size of your buffer.

How to allocate the array before calling strcpy?

Given:
char test[] = "bla-bla-bla";
Which of the two is more correct?
char *test1 = malloc(strlen(test));
strcpy(test1, test);
or
char *test1 = malloc(sizeof(test));
strcpy(test1, test);
This will work on all null-terminated strings, including pointers to char arrays:
char test[] = "bla-bla-bla";
char *test1 = malloc(strlen(test) + 1);
strcpy(test1, test);
You won't get the correct size of the array pointed to by char* or const char* with sizeof. This solution is therefore more versatile.
Neither:
#include <string.h>
char *mine = strdup(test);
You should use strlen, because sizeof will fail silently if you change test to be a run-time defined string. This means that strlen is a far safer idea than sizeof as it will keep working.
char test[]="bla-bla-bla";
char *test1 = malloc(strlen(test) + 1); // +1 for the extra NULL character
strcpy(test1, test);
I think sizeof is the correct one. Reason behind that is strlen(str) will give you length of the string( excluding the terminating null). And if you are using strcpy, it actually copy the whole string including the terminating null, so you will allocate one byte less if you use strlen in malloc. But sizeof gives the size of the string pointed by test, including the terminating null, so you will get correct size malloc chunk to copy the string including the terminating null.
1) definitely causes UB
2) may cause UB (if malloc fails)
I'd go with 2) as there is a better chance of the construct working as intended; or even better I'd write a version that works as intended (without UB) in all situations.
Edit
Undefined Behaviour in 1)
test1 will have space for the characters in test, but not for the terminating '\0'. The call to strcpy() will try to write a '\0' to memory that does not belong to test1, hence UB.
Undefined Behaviour in 2)
If the call to malloc() fails to reserve the requested memory, test1 will be assigned NULL. Passing NULL to strcpy() invokes UB.
The return value of calls to malloc() (and calloc() and friends) should always be tested to ensure the operation worked as expected.
(1) with strlen but not adding 1 is definitely incorrect. If you add 1, it would have the added benefit that it also works for pointers, not just arrays.
On the other hand, (2) is preferred as long as your string is actually an array, as it results in a compile-time constant, rather than a call to strlen (and thus faster and smaller code). Actually a modern compiler like gcc can probably optimize the strlen out if it knows the string is constant, but it may be hard for the compiler to determine this, so I'd always use sizeof when possible.
If it is a critical path, sizeof has advantage over strlen as it has an O(1) complexity which can save CPU cycles.

Strings in C: pitfalls and techniques

I will be coaching an ACM Team next month (go figure), and the time has come to talk about strings in C. Besides a discussion on the standard lib, strcpy, strcmp, etc., I would like to give them some hints (something like str[0] is equivalent to *str, and things like that).
Do you know of any lists (like cheat sheets) or your own experience in the matter?
I'm already aware of the books for the ACM competition (which are good, see particularly this), but I'm after tricks of the trade.
Thank you.
Edit: Thank you very much everybody. I will accept the most voted answer, and have duly upvoted others which I think are relevant. I expect to do a summary here (like I did here, asap). I have enough material now and I'm certain this has improved the session on strings immensely. Once again, thanks.
It's obvious but I think it's important to know that strings are nothing more than an array of bytes, delimited by a zero byte.
C strings aren't all that user-friendly as you probably know.
Writing a zero byte somewhere in the string will truncate it.
Going out of bounds generally ends bad.
Never, ever use strcpy, strcmp, strcat, etc.., instead use their safe variants: strncmp, strncat, strndup,...
Avoid strncpy. strncpy will not always zero delimit your string! If the source string doesn't fit in the destination buffer it truncates the string but it won't write a nul byte at the end of the buffer. Also, even if the source buffer is a lot smaller than the destination, strncpy will still overwrite the whole buffer with zeroes. I personally use strlcpy.
Don't use printf(string), instead use printf("%s", string). Try thinking of the consequences if the user puts a %d in the string.
You can't compare strings with if( s1 == s2 )
doStuff(s1);
You have to compare every character in the string. Use strcmp or better strncmp.
if( strncmp( s1, s2, BUFFER_SIZE ) == 0 )
doStuff(s1);
Abusing strlen() will dramatically worsen the performance.
for( int i = 0; i < strlen( string ); i++ ) {
processChar( string[i] );
}
will have at least O(n2) time complexity whereas
int length = strlen( string );
for( int i = 0; i < length; i++ ) {
processChar( string[i] );
}
will have at least O(n) time complexity. This is not so obvious for people who haven't taken time to think of it.
The following functions can be used to implement a non-mutating strtok:
strcspn(string, delimiters)
strspn(string, delimiters)
The first one finds the first character in the set of delimiters you pass in. The second one finds the first character not in the set of delimiters you pass in.
I prefer these to strpbrk as they return the length of the string if they can't match.
str[0] is equivalent to 0[str], or more generally str[i] is i[str] and i[str] is *(str + i).
NB
this is not specific to strings but it works also for C arrays
The strn* variants in stdlib do not necessarily null terminate the destination string.
As an example: from MSDN's documentation on strncpy:
The strncpy function copies the
initial count characters of strSource
to strDest and returns strDest. If
count is less than or equal to the
length of strSource, a null character
is not appended automatically to the
copied string. If count is greater
than the length of strSource, the
destination string is padded with null
characters up to length count.
confuse strlen() with sizeof() when using a string:
char *p = "hello!!";
strlen(p) != sizeof(p)
sizeof(p) yield, at compile time, the size of the pointer (4 or 8 bytes) whereas strlen(p) counts, at runtime, the lenght of the null terminated char array (7 in this example).
strtok is not thread safe, since it uses a mutable private buffer to store data between calls; you cannot interleave or annidate strtok calls also.
A more useful alternative is strtok_r, use it whenever you can.
kmm has already a good list. Here are the things I had problems with when I started to code C.
String literals have an own memory section and are always accessible. Hence they can for example be a return value of function.
Memory management of strings, in particular with a high level library (not libc). Who is responsible to free the string if it is returned by function or passed to a function?
When should "const char *" and when "char *" be used. And what does it tell me if a function returns a "const char *".
All these questions are not too difficult to learn, but hard to figure out if you don't get taught them.
I have found that the char buff[0] technique has been incredibly useful.
Consider:
struct foo {
int x;
char * payload;
};
vs
struct foo {
int x;
char payload[0];
};
see https://stackoverflow.com/questions/295027
See the link for implications and variations
I'd point out the performance pitfalls of over-reliance on the built-in string functions.
char* triple(char* source)
{
int n=strlen(source);
char* dest=malloc(n*3+1);
strcpy(dest,src);
strcat(dest,src);
strcat(dest,src);
return dest;
}
I would discuss when and when not to use strcpy and strncpy and what can go wrong:
char *strncpy(char* destination, const char* source, size_t n);
char *strcpy(char* destination, const char* source );
I would also mention return values of the ansi C stdlib string functions. For example ask "does this if statement pass or fail?"
if (stricmp("StrInG 1", "string 1")==0)
{
.
.
.
}
perhaps you could illustrate the value of sentinel '\0' with following example
char* a = "hello \0 world";
char b[100];
strcpy(b,a);
printf(b);
I once had my fingers burnt when in my zeal I used strcpy() to copy binary data. It worked most of the time but failed mysteriously sometimes. Mystery was revealed when I realized that binary input sometimes contained a zero byte and strcpy() would terminate there.
You could mention indexed addressing.
An elements address is the base address + index * sizeof element
A common error is:
char *p;
snprintf(p, 3, "%d", 42);
it works until you use up to sizeof(p) bytes.. then funny things happens (welcome to the jungle).
Explaination
with char *p you are allocating space for holding a pointer (sizeof(void*) bytes) on the stack. The right thing here is to allocate a buffer or just to specify the size of the pointer at compile time:
char buf[12];
char *p = buf;
snprintf(p, sizeof(buf), "%d", 42);
Pointers and arrays, while having the similar syntax, are not at all the same. Given:
char a[100];
char *p = a;
For the array, a, there is no pointer stored anywhere. sizeof(a) != sizeof(p), for the array it is the size of the block of memory, for the pointer it is the size of the pointer. This become important if you use something like: sizeof(a)/sizeof(a[0]). Also, you can't ++a, and you can make the pointer a 'const' pointer to 'const' chars, but the array can only be 'const' chars, in which case you'd be init it first. etc etc etc
If possible, use strlcpy (instead of strncpy) and strlcat.
Even better, to make life a bit safer, you can use a macro such as:
#define strlcpy_sz(dst, src) (strlcpy(dst, src, sizeof(dst)))

Resources