我试图从用户获得一些数据,并将其发送到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并发送一个合适的字符串。
当前回答
一般来说,与其删除不想要的数据,不如从一开始就避免写入数据。如果你不想在缓冲区中使用换行符,不要使用fgets。相反,请使用getc或fgetc或scanf。也许是这样的:
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
char Name[256];
char fmt[32];
if( snprintf(fmt, sizeof fmt, "%%%zd[^\n]", sizeof Name - 1) >= (int)sizeof fmt ){
fprintf(stderr, "Unable to write format\n");
return EXIT_FAILURE;
}
if( scanf(fmt, Name) == 1 ) {
printf("Name = %s\n", Name);
}
return 0;
}
注意,这种特殊的方法将不读取换行符,因此您可能希望使用像“%255[^\n]%*c”这样的格式字符串来丢弃它(例如,sprintf(fmt,“%%%zd[^\n]%%*c”,sizeof Name - 1);),或者可能在scanf后面加上getchar()。
其他回答
这就是我的解。非常简单。
// 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';
}
}
如果可以选择使用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的[安全问题]不应该被忽视。
下面的函数是我在Github上维护的字符串处理库的一部分。它从字符串中删除不需要的字符,这正是你想要的
int zstring_search_chr(const char *token,char s){
if (!token || s=='\0')
return 0;
for (;*token; token++)
if (*token == s)
return 1;
return 0;
}
char *zstring_remove_chr(char *str,const char *bad) {
char *src = str , *dst = str;
while(*src)
if(zstring_search_chr(bad,*src))
src++;
else
*dst++ = *src++; /* assign first, then incement */
*dst='\0';
return str;
}
一个示例用法是
Example Usage
char s[]="this is a trial string to test the function.";
char const *d=" .";
printf("%s\n",zstring_remove_chr(s,d));
Example Output
thisisatrialstringtotestthefunction
你可能想要检查其他可用的功能,甚至为项目贡献:) https://github.com/fnoyanisi/zString
一般来说,与其删除不想要的数据,不如从一开始就避免写入数据。如果你不想在缓冲区中使用换行符,不要使用fgets。相反,请使用getc或fgetc或scanf。也许是这样的:
#include <stdio.h>
#include <stdlib.h>
int
main(void)
{
char Name[256];
char fmt[32];
if( snprintf(fmt, sizeof fmt, "%%%zd[^\n]", sizeof Name - 1) >= (int)sizeof fmt ){
fprintf(stderr, "Unable to write format\n");
return EXIT_FAILURE;
}
if( scanf(fmt, Name) == 1 ) {
printf("Name = %s\n", Name);
}
return 0;
}
注意,这种特殊的方法将不读取换行符,因此您可能希望使用像“%255[^\n]%*c”这样的格式字符串来丢弃它(例如,sprintf(fmt,“%%%zd[^\n]%%*c”,sizeof Name - 1);),或者可能在scanf后面加上getchar()。
以最明显的方式删除换行符的步骤:
通过使用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){}。