问题
Having this:
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
char *up(char *);
int main() {
char initstr[20];
printf("enter string\n");
fgets(initstr, 20, stdin);
char *str = up(initstr);
printf("%s\n", str);
}
char *up(char *in) {
char *ret;
for (ret = in;
*in != '\n';
*(ret++) = toupper(*(in++))
);
return ret;
}
Run it as:
$./a.out
enter string
abc
#only new line from `printf("%s\n",str);`
From debugger
Hardware watchpoint 3: in
Old value = 0x7fffffffdc20 "abc\n"
New value = 0x7fffffffdc21 "bc\n"
Hardware watchpoint 2: ret
Old value = 0x7fffffffdc20 "abc\n"
New value = 0x7fffffffdc21 "bc\n"
Hardware watchpoint 3: in
Old value = 0x7fffffffdc21 "bc\n"
New value = 0x7fffffffdc22 "c\n"
Hardware watchpoint 2: ret
Old value = 0x7fffffffdc21 "bc\n"
New value = 0x7fffffffdc22 "c\n"
...
I can see that both variables are reducing, but I wanted to change the ret inline, char by char. But at the end (after loop), the ret is reduced to nothing, and the program will only output \n. So how can I achieve this in the loop head?
EDIT: Thanks to answer below, having in mind I have to return first address of pointer, I can implement loop_head-only function by this:
char *up(char *in){
char *ret;
size_t size=strlen(in);
for(ret=in;
*in!='\n';
*(ret++)=toupper(*(in++))
);
return (ret-size+1);
}
回答1:
The bug in up is you increment ret all the way to the newline (\n) and return ret pointing to this character in the string. You should instead return a pointer to the initial character.
- It is simpler to write this function using an index.
- packing all the logic into the
forclauses with an empty body is hard to read and error prone. - Note also that the string might not contain a newline, so it is safer to stop at the null terminator, the newline will not be changed by
toupper(). - Finally, you should not pass
charvalues totoupper()because this function and all functions from<ctype.h>is only defined for values of typeunsigned charand the special negative valueEOF. On platforms wherecharis signed by default, the string might contain negativecharvalues which may cause undefined behavior when passed totoupper(). Cast these as(unsigned char)to avoid this issue.
Here is a modified version:
#include <ctype.h>
#include <stdio.h>
char *up(char *s) {
for (size_t i = 0; s[i] != '\0'; i++) {
s[i] = toupper((unsigned char)s[i]);
}
return s;
}
int main() {
char initstr[20];
printf("enter string\n");
if (fgets(initstr, sizeof initstr, stdin)) {
char *str = up(initstr);
printf("%s\n", str);
}
return 0;
}
来源:https://stackoverflow.com/questions/62233572/how-to-change-single-char-in-string-array