我正在使用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,它运行得很好,有什么建议吗?
答案 0 :(得分:1)
尝试删除最后的" s"在"%[^ \ n] s"
答案 1 :(得分:1)
模式%[^n]s
是scanf
的有效格式,但它不是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'
结尾。
答案 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;
}