问题
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
for
clauses 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
char
values totoupper()
because this function and all functions from<ctype.h>
is only defined for values of typeunsigned char
and the special negative valueEOF
. On platforms wherechar
is signed by default, the string might contain negativechar
values 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