我试图从用户获得一些数据,并将其发送到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并发送一个合适的字符串。


当前回答

如果可以选择使用getline(不要忽略其安全性问题),如果希望使用大括号指针,则可以避免使用字符串函数,因为getline返回的是字符数。如下图所示

#include <stdio.h>
#include <stdlib.h>
int main()
{
    char *fname, *lname;
    size_t size = 32, nchar; // Max size of strings and number of characters read
    fname = malloc(size * sizeof *fname);
    lname = malloc(size * sizeof *lname);
    if (NULL == fname || NULL == lname)
    {
        printf("Error in memory allocation.");
        exit(1);
    }
    printf("Enter first name ");
    nchar = getline(&fname, &size, stdin);
    if (nchar == -1) // getline return -1 on failure to read a line.
    {
        printf("Line couldn't be read..");
        // This if block could be repeated for next getline too
        exit(1);
    }
    printf("Number of characters read :%zu\n", nchar);
    fname[nchar - 1] = '\0';
    printf("Enter last name ");
    nchar = getline(&lname, &size, stdin);
    printf("Number of characters read :%zu\n", nchar);
    lname[nchar - 1] = '\0';
    printf("Name entered %s %s\n", fname, lname);
    return 0;
}

注意:getline的[安全问题]不应该被忽视。

其他回答

优雅的方式:

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字符。

当然,还有其他原因。

size_t ln = strlen(name) - 1;
if (*name && name[ln] == '\n') 
    name[ln] = '\0';

也许最简单的解决方案是使用我最喜欢的一个鲜为人知的函数strcspn():

buffer[strcspn(buffer, "\n")] = 0;

如果你想让它也处理'\r'(比如,如果流是二进制的):

buffer[strcspn(buffer, "\r\n")] = 0; // works for LF, CR, CRLF, LFCR, ...

该函数会计算字符的数量,直到遇到'\r'或'\n'(换句话说,它会找到第一个'\r'或'\n')。如果它没有碰到任何东西,它就会停在'\0'(返回字符串的长度)。

请注意,即使没有换行符,这也可以正常工作,因为strcspn在'\0'处停止。在这种情况下,整行代码只是将“\0”替换为“\0”。

对于单个“\n”切边,

void remove_new_line(char* string)
{
    size_t length = strlen(string);
    if((length > 0) && (string[length-1] == '\n'))
    {
        string[length-1] ='\0';
    }
}

对于多个“\n”切边,

void remove_multi_new_line(char* string)
{
  size_t length = strlen(string);
  while((length>0) && (string[length-1] == '\n'))
  {
      --length;
      string[length] ='\0';
  }
}

Tim Čas one line对于调用fgets获得的字符串来说非常神奇,因为您知道它们在末尾包含一个换行符。

如果您处于不同的上下文中,并且希望处理可能包含多个换行符的字符串,则可能需要查找strrspn。它不是POSIX,这意味着您不会在所有unix上找到它。我为自己的需要写了一个。

/* Returns the length of the segment leading to the last 
   characters of s in accept. */
size_t strrspn (const char *s, const char *accept)
{
  const char *ch;
  size_t len = strlen(s);

more: 
  if (len > 0) {
    for (ch = accept ; *ch != 0 ; ch++) {
      if (s[len - 1] == *ch) {
        len--;
        goto more;
      }
    }
  }
  return len;
}

对于那些在C中寻找等效Perl chomp的人来说,我认为这就是它(chomp只删除后面的换行符)。

line[strrspn(string, "\r\n")] = 0;

strrcspn函数:

/* Returns the length of the segment leading to the last 
   character of reject in s. */
size_t strrcspn (const char *s, const char *reject)
{
  const char *ch;
  size_t len = strlen(s);
  size_t origlen = len;

  while (len > 0) {
    for (ch = reject ; *ch != 0 ; ch++) {
      if (s[len - 1] == *ch) {
        return len;
      }
    }
    len--;
  }
  return origlen;
}