编程很新。我正在尝试创建一个txt文件,询问用户文件名,然后文本文件。起初我得到一个关于null的错误所以我放了一个if语句,似乎代码无法打开具有该名称的文件。试图做一些研究并最终做出一些改变,但仍然导致同样的错误。
include <stdio.h>;
include <stdlib.h>;
int main()
{
char *fileName[100];
char inputText[100];
printf("What is the .txt file name? \n");
scanf_s("%123s", &fileName);
strcat(fileName, ".txt");
FILE *textFile;
textFile = fopen_s(&textFile, fileName, "w");
if (textFile != 0)
{
printf("Cannot get file");
return -1;
}
printf("What should be written in the text file? \n");
scanf_s("%123s", &inputText);
fprintf(textFile, "%s", inputText);
fclose(textFile);
return 0;
}
答案 0 :(得分:2)
你在学习C时可以做的最重要的事情是 - 慢下来。有很多东西需要学习,你必须一步一步。猜测,编译,查看是否有任何变化,改变其他内容和(重复)是没有用的。 查一查。
也就是说,您对stdin
/ stdout
的基本输入/输出以及为写打开的文件感兴趣。目前还不清楚您是使用scanf_s
还是使用非_s
版本的窗口,因为它们在下面混合搭配。无论如何,主要区别在于所需的参数。
在C中,您声明数组保存文件名和输入文本以保存100
个字符。使用字符串时,每个字符串最后都需要一个 nul-terminatedating 字符('\0'
...或仅0
,数字相同)。这意味着您可以在99
或+1
中存储最多个filename
个字符inputtext
nul-terminatedating 字符(旁注:C通常避免使用混合大小写的变量名来支持所有小写,但这取决于你)
为防止在filename
或inputtext
结束之后写作,您需要确保限制您尝试存储的字符数。您可以使用格式说明符的 field-width 选项执行此操作。如,
scanf ("%99s", inputtext);
或Windows _s
版本:
scanf_s ("%99s", inputtext, 100u);
但是,使用"%99s"
的格式说明符不允许输入包含空格,因为%s
格式说明符将读取到第一个空白或换行符。其次,由于按 [Enter] ,它不会在用户输入结束时读取(或以任何方式处理)'\n'
。如果您的下一个输入是字符输入,这将导致问题,因为scanf
将乐意接受'\n'
作为要读取的下一个字符。现在%s
将跳过前导空格('\n'
是空白)不应该出现问题,但这是您在形成像scanf
<这样简单的事情时必须经过的思维过程。 em>格式字符串。
养成每次输入流中所有字符的习惯。这样你就不会因为一些你无法解释的错误而措手不及。
要允许输入包含空格,可以使用scanf
的字符类格式说明符。例如,您可以使用"%99[^\n]"
作为格式字符串。但是,字符类不会自动忽略前导空格,但您可以通过在space
开始格式说明符之前留下%
来提供这种灵活性,例如: " %99[^\n]"
。这很重要。 (这也是fgets
或POSIX getline
优先于scanf
处理用户输入的原因。
现在,您如何处理输入缓冲区中的'\n'
(例如stdin
)?除了保留space
之外,您还可以在格式字符串中使用赋值抑制运算符。 " %99[^\n]%*c"
%*c
是用于读取字符%c
的格式说明符,但是通过包含'*'
(赋值抑制运算符),您可以将scanf
告诉阅读并放弃角色。
在进行用户输入时,仅提供正确的格式说明符是不够的。您必须确认您实际收到了预期的输入。对于任何输入例程,这至少意味着检查scanf
(或fgets
或getline
等的回报。)。对于scanf
,返回的是&#34; 匹配计数&#34;,这是根据格式字符串执行的成功转换次数。例如%s
(或%[^\n]
)构成了单次转化的请求。 (与分配抑制运算符关联的任何转换都不包含在匹配计数中)因此,您的预期回报是格式字符串中的转换次数。将它们组合在一起,您可以使用:{/ p>处理inputtext
printf ("What should be written in the text file? "); /* prompt */
/* validate user input -- limit to 99 chars (+1 for nul char) */
if (scanf (" %99[^\n]%*c", inputtext) != 1) {
fprintf (stderr, "error: invalid input (inputtext).\n");
return 1;
}
同样的事情也适用于filename
吗?答:不。为什么?您计划在用户输入之后将".txt"
附加到filename
,对吗? ".txt"
中有多少个字符?答案:4
(对于组合字符串,您只有1
nul-terminated char。那你必须限制filename
到什么? " %95[^\n]%*c"
要执行文件I / O,您有多种选择。到目前为止, fstream 缓冲I / O函数是基本文本I / O最常用的。要读取或写入文件,必须先打开FILE
流。您可以通过声明FILE *pointer
然后调用fopen
,然后检查返回值(pointer
的值)来验证文件是否已成功打开。相同的规则,格式说明符等适用于读取/写入文件(在磁盘上),就像写入stdin
或stdout
一样,因为所有这些只是来自C&#39的文件的观点。
考虑到这一点,你可以做类似以下的事情:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
enum { MAXC = 100 };
int main (void) {
/* declare and initialize variables */
char filename[MAXC] = "", inputtext[MAXC] = "";
FILE *fp = NULL;
printf ("What is the .txt file name? "); /* prompt */
/* validate user input -- limit to 95 chars */
if (scanf (" %95[^\n]%*c", filename) != 1) {
fprintf (stderr, "error: invalid input (filename).\n");
return 1;
}
strcat (filename, ".txt"); /* +4 chars = 99 chars */
/* open file/validate file open for reading */
if (!(fp = fopen (filename, "w"))) {
fprintf (stderr, "error: file open failed '%s'.\n", filename);
return 1;
}
printf ("What should be written in the text file? "); /* prompt */
/* validate user input -- limit to 99 chars (+1 for nul char) */
if (scanf (" %99[^\n]%*c", inputtext) != 1) {
fprintf (stderr, "error: invalid input (inputtext).\n");
return 1;
}
/* output status to stdout & inputtext to fp */
printf ("\nwriting to '%s'\n%s\n", filename, inputtext);
fprintf (fp, "%s\n", inputtext);
if (fclose (fp)) /* close file - validate stream close */
fprintf (stderr, "error: on file stream close.\n");
return 0;
}
注意 写入到文件后,检查fclose
的返回值以确保写入期间未发生流错误非常重要。 (关闭你读取的流,那个问题不在那里)
示例使用/输出
$ ./bin/inputtext
What is the .txt file name? dat/inputtext
What should be written in the text file? A quick brown fox jumps over the lazy dog.
writing to 'dat/inputtext.txt'
A quick brown fox jumps over the lazy dog.
检查文件内容:
$ cat dat/inputtext.txt
A quick brown fox jumps over the lazy dog.
查看代码,如果您对代码中的任何字符
有任何疑问,请告知我们。每个人都需要一点帮助才能开始,而我能传达的最重要的事情就是减慢和理解你编写的每个字符,阅读和理解你的编译器警告(修复每一个),如果你不确定你在做什么,仔细查看。 Linux / Unix上的man function
或Windows的MSDN搜索(例如scanf_s,...)。它们以合理清晰的术语告诉您每个函数的每个参数的类型和要求(并且很多都提供了示例)。
祝你好运。
答案 1 :(得分:0)
根据MSDN文档,fopen_s采用FILE **形式的参数而不是FILE *。它还返回错误代码而不是文件句柄,这不是函数的返回值。所以你在这段代码中所做的就是用一些不相关的整数覆盖你的文件句柄。如果将错误代码存储在另一个变量中,则应解决该问题。
有关fopen_s的更多信息,请访问:https://msdn.microsoft.com/en-us/library/z5hh6ee9.aspx