我试图从用户获得一些数据,并将其发送到gcc中的另一个函数。代码是这样的。
printf("Enter your Name: ");
if (!(fgets(Name, sizeof Name, stdin) != NULL)) {
fprintf(stderr, "Error reading Name.\n");
exit(1);
}
然而,我发现它最后有一个换行符\n字符。如果我输入John,它最终会发送John\n。我如何删除\n并发送一个合适的字符串。
我试图从用户获得一些数据,并将其发送到gcc中的另一个函数。代码是这样的。
printf("Enter your Name: ");
if (!(fgets(Name, sizeof Name, stdin) != NULL)) {
fprintf(stderr, "Error reading Name.\n");
exit(1);
}
然而,我发现它最后有一个换行符\n字符。如果我输入John,它最终会发送John\n。我如何删除\n并发送一个合适的字符串。
当前回答
以最明显的方式删除换行符的步骤:
通过使用strlen(), header string.h来确定NAME内部字符串的长度。注意,strlen()不计算结束的\0。
size_t sl = strlen(NAME);
查看字符串是否以一个\0字符(空字符串)开头或只包含一个\0字符。在这种情况下,sl将为0,因为如上所述strlen()不会计算\0,并在它第一次出现时停止:
if(sl == 0)
{
// Skip the newline replacement process.
}
检查正确字符串的最后一个字符是否是换行符'\n'。如果是这种情况,将\n替换为\0。注意,索引计数从0开始,所以我们需要执行NAME[sl - 1]:
if(NAME[sl - 1] == '\n')
{
NAME[sl - 1] = '\0';
}
请注意,如果您只在fgets()字符串请求时按下Enter(字符串内容仅由换行符组成),则NAME中的字符串此后将成为空字符串。
我们可以结合第二步。和3。通过使用逻辑运算符&&,将它们组合在一个if语句中:
if(sl > 0 && NAME[sl - 1] == '\n')
{
NAME[sl - 1] = '\0';
}
完成的代码:
size_t sl = strlen(NAME);
if(sl > 0 && NAME[sl - 1] == '\n')
{
NAME[sl - 1] = '\0';
}
如果你更喜欢一个函数使用这种技术,一般处理fgets输出字符串,而不需要每次都重新输入,这里是fgets_newline_kill:
void fgets_newline_kill(char a[])
{
size_t sl = strlen(a);
if(sl > 0 && a[sl - 1] == '\n')
{
a[sl - 1] = '\0';
}
}
在您提供的示例中,它将是:
printf("Enter your Name: ");
if (fgets(Name, sizeof Name, stdin) == NULL) {
fprintf(stderr, "Error reading Name.\n");
exit(1);
}
else {
fgets_newline_kill(NAME);
}
注意,如果输入字符串中嵌入了\0,则此方法不起作用。如果是这样的话,strlen()将只返回第一个\0之前的字符数。但这并不是一种常见的方法,因为大多数字符串读取函数通常在第一个\0处停止,直到该空字符。
除了这个问题本身。尽量避免双重否定,这会使你的代码不清晰:(fgets(Name, sizeof Name, stdin) != NULL){}。你可以简单地执行if (fgets(Name, sizeof Name, stdin) == NULL){}。
其他回答
如果每一行都有'\n',则直接从fgets输出中删除'\n'
line[strlen(line) - 1] = '\0';
否则:
void remove_newline_ch(char *line)
{
int new_line = strlen(line) -1;
if (line[new_line] == '\n')
line[new_line] = '\0';
}
size_t ln = strlen(name) - 1;
if (*name && name[ln] == '\n')
name[ln] = '\0';
以最明显的方式删除换行符的步骤:
通过使用strlen(), header string.h来确定NAME内部字符串的长度。注意,strlen()不计算结束的\0。
size_t sl = strlen(NAME);
查看字符串是否以一个\0字符(空字符串)开头或只包含一个\0字符。在这种情况下,sl将为0,因为如上所述strlen()不会计算\0,并在它第一次出现时停止:
if(sl == 0)
{
// Skip the newline replacement process.
}
检查正确字符串的最后一个字符是否是换行符'\n'。如果是这种情况,将\n替换为\0。注意,索引计数从0开始,所以我们需要执行NAME[sl - 1]:
if(NAME[sl - 1] == '\n')
{
NAME[sl - 1] = '\0';
}
请注意,如果您只在fgets()字符串请求时按下Enter(字符串内容仅由换行符组成),则NAME中的字符串此后将成为空字符串。
我们可以结合第二步。和3。通过使用逻辑运算符&&,将它们组合在一个if语句中:
if(sl > 0 && NAME[sl - 1] == '\n')
{
NAME[sl - 1] = '\0';
}
完成的代码:
size_t sl = strlen(NAME);
if(sl > 0 && NAME[sl - 1] == '\n')
{
NAME[sl - 1] = '\0';
}
如果你更喜欢一个函数使用这种技术,一般处理fgets输出字符串,而不需要每次都重新输入,这里是fgets_newline_kill:
void fgets_newline_kill(char a[])
{
size_t sl = strlen(a);
if(sl > 0 && a[sl - 1] == '\n')
{
a[sl - 1] = '\0';
}
}
在您提供的示例中,它将是:
printf("Enter your Name: ");
if (fgets(Name, sizeof Name, stdin) == NULL) {
fprintf(stderr, "Error reading Name.\n");
exit(1);
}
else {
fgets_newline_kill(NAME);
}
注意,如果输入字符串中嵌入了\0,则此方法不起作用。如果是这样的话,strlen()将只返回第一个\0之前的字符数。但这并不是一种常见的方法,因为大多数字符串读取函数通常在第一个\0处停止,直到该空字符。
除了这个问题本身。尽量避免双重否定,这会使你的代码不清晰:(fgets(Name, sizeof Name, stdin) != NULL){}。你可以简单地执行if (fgets(Name, sizeof Name, stdin) == NULL){}。
这就是我的解。非常简单。
// Delete new line
// char preDelete[256] include "\n" as newline after fgets
char deletedWords[256];
int iLeng = strlen(preDelete);
int iFinal = 0;
for (int i = 0; i < iLeng; i++) {
if (preDelete[i] == '\n') {
}
else {
deletedWords[iFinal] = preDelete[i];
iFinal++;
}
if (i == iLeng -1 ) {
deletedWords[iFinal] = '\0';
}
}
优雅的方式:
Name[strcspn(Name, "\n")] = 0;
略显丑陋的方式:
char *pos;
if ((pos=strchr(Name, '\n')) != NULL)
*pos = '\0';
else
/* input too long for buffer, flag error */
有点奇怪的方式:
strtok(Name, "\n");
注意,如果用户输入一个空字符串(即只按Enter), strtok函数就不能正常工作。它保留\n字符。
当然,还有其他原因。