将char数组复制到另一个而不复制换行符

时间:2014-11-13 21:29:52

标签: c arrays printf fgets

我正在使用fgets读取char数组中的字符串,然后我想将指针移到5个索引上并将数组的其余部分复制到一个单独的数组中,但我不希望它复制一个换行符;所以我有这样的事情:

char str1[45], str2[50];
fgets(str2, 50, stdin);
*str2 += 5;
sprintf(str1, "%[^\n]s", str2);

但是当我尝试编译时,我收到的错误是:

unknown conversion type character â[â in format [-Wformat]

我很确定我之前使用了“%[^ \ n] s”和scanf,它运行得很好,有什么建议吗?

6 个答案:

答案 0 :(得分:1)

尝试删除最后的" s"在"%[^ \ n] s"

答案 1 :(得分:1)

模式%[^n]sscanf的有效格式,但它不是printf(或sprintf)的有效格式说明符。

此外,*str2 += 5不会跳过前5个字符(因为它似乎是意图),而是为str2的第一个元素中存储的字节添加5。 str2 = str2 + 5将无法编译,因为str2是一个数组。您可以将结果分配给临时或直接传递给sprintf。

这是一种更好的方式来做你要求的事情:

size_t len;
char *str1 = NULL, str2[50];
fgets(str2, 50, stdin);
len = strlen(str2);
if (len > 5) {
  if (str2[len-1] == '\n') {
    str2[len-1] = '\0'; // remove newline
    len--;
  }
  str1 = str2 + 5;
  len -= 5;
}

if (str1 != NULL) {
    // do stuff
}

答案 2 :(得分:1)

"%[^\n]s" ok 代表scanf(),但printf()没有。注意:当然"s"是多余的。

存在各种方法来修剪尾随\n。推荐

if (fgets(str2, 50, stdin) == NULL) HAnlde_EOForIOError();
size_t len = strlen(str2);
if (len > 0 && str2[len-1] == '\n') len--;  

if (len < 5) Handle_ShortString();
memcpy(str1, str2 + 5, len-5+1);

请注意,从fegts()返回的字符串不会始终'\n'结尾。

请参阅trimming-fgets

答案 3 :(得分:0)

就个人而言,我只是通过简单的for循环从头开始实现它。

char str1[45], str2[50];
fgets(str2, 50, stdin);
size_t len = strlen(str2);
for (size_t k = 5; k < len; k += sizeof(char)) {
    str1[k - 5] = str2[k];
}

答案 4 :(得分:0)

要正确解决此问题,您不能忽视您正在处理大小有限的C数组这一事实。副本不仅必须根据需要在换行符处停止,还必须确保目标数组正确地为null终止,并且它不会溢出。

为此,最好编写一个函数,如:

#include <string.h>

/* Copy src to dst, until the point that a character from the bag set
 * is encountered in src.(That character is not included in the copy.
 * Ensures that dst is null terminated, unless dstsize is zero.
 * dstsize gives the size of the dst.
 * Returns the number of characters required to perform a complete copy;
 * if this exceeds dstsize, then the copy was truncated.
 */
size_t copyspan(char *dst, size_t dstsize, const char *src, const char *bag)
{
   size_t ideal_length = strcspn(src, bag); /* how many chars to copy */
   size_t limited_length = (ideal_length < dstsize) ? ideal_length : dstsize - 1;
   if (dstsize > 0) {
     memcpy(dst, src, limited_length);
     dst[limited_length] = 0;
   }
   return ideal_length + 1;
}

使用此功能,我们现在可以:

if (copyspan(str1, str2, "\n") > sizeof str1) {
  /* oops, truncated: handle this somehow */
}

当然,还有fgets可能已截断原始数据的问题。

仅处理fgets通常返回的尾随换行符(除了溢出行或文件未被换行符终止之外)通常如下所示:

{
  char line[128];
  /*...*/
  if (fgets(line, sizeof line, file)) {
    char *pnl = strchr(line, '\n'); /* obtain pointer to first newline */
    if (pnl != 0)                   /* if found, overwrite it with null */
      *pnl = 0;
  }
  /*...*/
}

如果你在许多地方进行这种线读,最好是制作一个包装器,而不是重复这个逻辑。

答案 5 :(得分:0)

#include <stdio.h>

int main(void){
    char str1[45], str2[50];

    if(fgets(str2, sizeof str2, stdin)){
        int i=0, j;
        for(j=0; str2[j] && str2[j] != '\n' && j < 5; ++j)
            ;
        if(j == 5){//move success
            while(str2[j] && str2[j] != '\n')
                str1[i++] = str2[j++];
            str1[i]=0;
            puts(str1);
        }
    }
    return 0;
}