So let's say I have a cha开发者_如何学Cr and I want to strcat() it to a char array in a single line of code. For [a non-practical] example:
strcat("ljsdflusdfg",getchar());
Or I wanted to do the reverse, what would be the appropriate function to concat or typecast strings, regardless of data type? Or perhaps there is some syntax I'm missing...
Here's an example. It compiles just fine but crashes.
char* input(){
char* inp="";
while(1){
char c=getchar();
if(c){
if(c=='\n'||c==EOF){
break;
}else{
strcat(inp,(char*)c);
}
}
}
return inp;
}
strcat
treats its argument as a pointer to a nul-terminated string. Casting a char
to a char *
is just dangerous, and I can imagine no reason it would ever be useful (not to imply that you're stupid for trying it - everyone makes silly mistakes when they learn. That's why we're here.)
The reason is that it would interpret the single byte char
, plus the extra sizeof(char*) - sizeof(char)
(usually 3) bytes surrounding that char
, as a pointer, which would point to... anywhere. You have no way of knowing where it points, since 3 of those bytes are beyond your control, and thus no way of knowing whether it points to valid data.
You might take this as a second approach:
strcat(inp, &c);
This time, you'd be doing better, since &c
is an expression of type char *
and no casts are required. But again, strcat
assumes it's argument is a nul-terminated string, and since you have no way of guaranteeing a nul byte after your char
data, this won't do.
The best way is this:
size_t len = strlen(inp); // this may already be calculated somewhere else
...
inp[len++] = c; // add c as the last character, and adjust our len
inp[len] = '\0'; // add a new nul terminator to our string
UPDATE:
Actually, I lied. The best way is to use the standard library function fgets
, which appears to be doing more or less what you're trying to do. Truthfully I forgot it, but if this is a homework assignment your professor may not want you using fgets
so that you can learn how to do it manually. However, if this isn't homework, fgets
does exactly what you're looking for. (Actually, the third approach is well on its way to reimplementing fgets
or fgets
-like functionality.)
I would also add some other commentary on your input
function:
char* inp = "";
will point to read-only data. A flaw in the C standard (for backwards compatability) allows string literals to be assigned tochar*
types instead ofconst char *
types as it (IMHO) should be.
There are several ways to approach this, but the best is dynamic allocation. Use themalloc
function to reserve some data, keep track of how much you've used in your function, and use therealloc
function if you end up needing more room to store it. If you need help with that, I'm sure you'll be back here (hopefully not too soon) with another question. :)getchar()
returns anint
, becauseEOF
is defined to be outside the normal range of achar
. In order to distinguish between anychar
andEOF
, it's best to makec
anint
. Otherwise a perfectly valid character may signalEOF
. Be sure to castc
down to achar
when you add it to the string, though.
strcat(inp,(char*)c);
That is trying to concat the contents of the memory at where ever 'c' (as a memory location) is until it finds a zero.
A better way is to create an empty string of whatever maximum size you think is reasonable, fill it with zeros and then just insert 'c' at the current last position
If you wish to concatenate a single char
onto a string, you can use strncat()
and specify the number of characters to concatenate as 1
. But note that:
- The destination buffer must have sufficient space; and
- In C89, you must have an actual
char
object to take the address of (so you can't directly concatenate the result ofgetchar()
.
For example:
char str[5] = "foo";
char c;
int ch;
if ((ch = getchar()) != EOF) {
c = ch;
strncat(str, &c, 1);
}
In C99, you can use a compound literal and the second restriction does not apply:
char str[5] = "foo";
int ch;
if ((ch = getchar()) != EOF) {
strncat(str, &(char){ ch }, 1);
}
This won't work because the *inp char pointer doesn't have any memory backing it up. When you declared it to be char *inp = "";, you only gave it the address of an empty string. If you had given the following declaration char *inp = "abcdefg", then you could have written 7 chars to it before you overwrote the '\0' and got into trouble.
You will need to dynamically increase the size of the backing memory as you input more and more characters. You will also have the problem of knowing when to free the memory so you don't get memory leaks.
Also, your strcat needs to have '&' before the c.
First off, you are returning a pointer to a stack allocated array. This is undefined bahavior. Secondly, you are attempting to write chars into unallocated memory. Thirdly, the type of inp
is const char*
not char*
.
You want something like:
char* input(char *dest) {
strcpy(dest,"");
while(1){
char c=getchar();
if(c){
if(c=='\n'||c==EOF){
break;
}else{
strcat(inp,&c);
}
}
}
return dest;
}
Your code crashes because strcat expects null-terminated strings for both its parameters.
If you want to concatenate a char, you need to first create a null-terminated string from it.
char c[2] = {0,0};
c[0] = getchar();
strcat(inp, c);
But don't use strcat, unless you can guarantee that the input string has allocated space for that extra character. Better to you strncat which also includes a parameter for the amount of space in the first parameter (the dest).
I recommend reading this first.
One simple way is to use snprintf:
char newString[50+1];
snprintf(newString, sizeof(newString), "%s%c", "ljsdflusdfg", getchar());
It's a simple solution, but does require that you roughly know how big the string is going to be ahead of time.
Notes: I use the +1 to remind myself that there needs to be room for the null termination, and snprintf is better than sprintf as it is given the size of the buffer to prevent buffer overrun.
Cast char to char array?
It's just like saying you want to cast a char into string.
You just can't do that directly.
Instead of char, place it in an array (myChar[]).
Afterwhich, strcat it with your original char array.
精彩评论