【问题标题】:fprintf statement not executing properly in code blocksfprintf 语句未在代码块中正确执行
【发布时间】:2014-06-26 11:29:10
【问题描述】:

我尝试在 code::blocks 中运行该程序以显示名称列表,但在 fprintf 处停止执行。我尝试了另一个使用 fprintf 的程序(如下所示),它似乎工作正常

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
int main()
{
   FILE *ptr;
   ptr=fopen("D:\\test.txt","w+");
   char a[5];
   char i='a',j='a',k='a',l='a';
   a[0]='l';
   a[1]='a';
   for(i='a';i<=121;i++)
   {
      a[2]=i;
      for(j='a';j<=121;j++)
      {
        a[3]=j;
        switch(j)
           case 'a':
           case 'e':
           case 'i':
           case 'o':
           case 'u': 
             for(k='a';k<=121;k++)
             {
               a[4]=k;
               for(l='a';l<=117;l++)
               {
                  switch(l)
                     case 'a':
                     case 'e':
                     case 'i':
                     case 'o':
                     case 'u':{a[5]=l;fprintf(ptr,"%s",a);}
               }
             }
      }
   }
   fclose(ptr);
   return 0;
}

这是完美运行的程序

#include<stdlib.h>
#include<stdio.h>
#include<string.h>
main()
{
    char a[50],b[50];
    printf("Enter a name\n");
    gets(b);
    FILE *ptr;
    ptr=fopen("D:\\test.txt","w+");
    fprintf(ptr,"%s",b);
    rewind(ptr);
    fscanf(ptr,"%s",&a);
    printf("%s",a);
    fclose(ptr);
}

【问题讨论】:

  • 执行停止可能意味着什么。在使用结果之前,您应该检查 fopen() 是否有效。在使用%s 打印它们之前,您还应该确保您的字符串为空终止,或者确保将打印的长度限制为有效的长度。您可能也希望在输出中的某处换行。另外,永远不要使用gets()。甚至在演示代码中也没有。这是一个坏习惯。它不再是标准 C 的一部分。您应该使用 'z' 代替 121,并使用 'u' 代替 117。
  • 嗯;您还声明了char a[5];,这意味着您只能通过a[4] 引用a[0]。您的代码尝试写入a[5],这超出了界限(错误)。 noelkdanswer 悄悄地将定义更改为 char a[7];,但应该大声疾呼,因为这是一个至关重要的变化。

标签: c printf


【解决方案1】:

我已经整理了你的代码:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(int argc, char *argv[]) {

      FILE *ptr = NULL;
      char a[7];

      /* Attempt to open the output file, and exit if something goes wrong. */
      ptr = fopen("D:\\test.txt", "w+");
      if (!ptr) { return 1; }  

      /* End the string with a NUL-terminator byte. */
      a[0] = 'l';
      a[1] = 'a';
      a[6] = 0;

      for (a[2] = 'a'; a[2] <= 121; a[2]++) {
            for (a[3] = 'a'; a[3] <= 121; a[3]++) {
                  switch (a[3]) {
                        case 'a': case 'e': case 'i': case 'o': case 'u':
                              for (a[4] = 'a'; a[4] <= 121; a[4]++) {
                                    for (a[5] = 'a'; a[5] <= 117; a[5]++) {
                                          switch (a[5]) {
                                                case 'a': case 'e': case 'i': case 'o': case 'u':
                                                      fprintf(ptr, "%s\n", a);
                                                break;
                                          }
                                    }
                              }
                        break;
                  }
            }
      }

      fclose(ptr);
      return 0;

}

我认为问题在于字符串a 不包含零终止符字节,所以我添加了一个。您还应该确保在尝试写入文件之前成功打开文件,所以我也添加了这一点。代码中相关部分已留下注释。

我已经验证这一切都与this 一起工作。

【讨论】:

  • 谢谢,代码完美无瑕。我对编程比较陌生,但字符串不应该以 \0 结尾
  • 看看a[6] = 0这一行,这是将数组的最后一个元素设置为0,还要注意如果你说char a[7]它的索引来自0-6,即你不能使用a[7] 不会破坏内存。如果答案有帮助,请consider accepting it
  • 我不相信重新格式化(但最好添加 break 语句),但我相信'not null terminate in the original'。
  • 我添加了一个社区 Wiki 答案,其中包含我喜欢的格式。我不需要任何功劳,但我不可能在评论中格式化代码,也不愿意对你的答案做出如此重大的改变。
  • 不错的答案,但我没有问“[Jonathan Leffler] 如何格式化代码”
【解决方案2】:

我已在您自己的帖子中缩进了您的代码。
您必须正确缩进您的代码,以避免程序一团糟。

缩进后,我看到你使用switch()不好。
在实践中,大括号应始终与 switch 一起使用,即使不是绝对必要的。这里有一个很好的模型需要考虑:

 switch(expression)
 {
    case 1:
      sentences...
      break;
    case 2:
      sentences...
      break;
    default:
      sentences...
      break;
 }

过多的嵌套循环和切换语句使程序的逻辑难以遵循。

【讨论】:

  • 实际上,即使它非常非常规,原始的无括号switch也是有效的C。如果你说在实践中,大括号应该总是与switch 一起使用,即使不是绝对必要,我也会完全同意你的看法。
  • @JonathanLeffler:我的本意是这么说的。最后,我做了你建议的更改。
【解决方案3】:

在回复Noelkdcomment 询问“@JonathanLeffler 你介意重新格式化一下吗?”时,这或多或少是我格式化它的方式。

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int main(void)
{
    const char file[] = "D:\\test.txt"; 
    FILE *ptr = fopen(file, "w+");
    char a[7] = "la";
    if (ptr == 0)
    {
        fprintf(stderr, "Failed to open file %s for writing\n", file);
        return 1;
    }
    for (int i = 'a'; i <= 'z'; i++)
    {
        a[2] = i;
        for (int j = 'a'; j <= 'z'; j++)
        {
            a[3] = j;
            switch (j)
            {
            case 'a':
            case 'e':
            case 'i':
            case 'o':
            case 'u':
                for (int k = 'a'; k <= 'z'; k++)
                {
                    a[4] = k;
                    for (int l = 'a'; l <= 'u'; l++)
                    {
                        switch (l)
                        {
                        case 'a':
                        case 'e':
                        case 'i':
                        case 'o':
                        case 'u':
                            a[5] = l;
                            fprintf(ptr, "%s\n", a);
                            break;
                        }
                    }
                }
                break;
            }
        }
    }
    fclose(ptr);
    return 0;
}

主要区别:

  1. 使用命名字符串作为文件名,所以如果需要我可以在错误消息中报告文件名。
  2. 如果无法打开文件报告错误。
  3. 初始化ptr,而不是稍后分配。
  4. 调整a的大小。
  5. 初始化a
  6. for 循环中使用C99/C++ 声明以避免在顶部声明ijkl。如果强制使用 C89,那么我不会包含初始化程序,因为变量是在使用时设置的。
  7. 每个switch 的操作都用大括号括起来。
  8. 每个 switch 中的每个 case 都以 break 结尾(即使在技术上不必要;它使未来的更改更加可靠)。
  9. 在打印操作中添加换行符。
  10. 移除动作周围现在多余的大括号。

我非常喜欢大括号布局的Allman,但承认也有同样强烈的观点支持替代方案。大括号布局不是我不喜欢 noelkd 重新格式化的原因之一。

我还使用了四个空格的缩进。很长一段时间以来,我使用的制表位设置为 4 的制表符,但在过去十年左右的时间里我已经切换到无制表符。当程序忽略任何参数时,我使用显式的int main(void)。我编译使用:

$ gcc -g -O3 -std=c99 -Wall -Wextra -Wmissing-prototypes -Wstrict-prototypes \
>      -Werror  fp2.c -o fp2

(或者我使用-std=c11)。我有时会使用额外的选项,例如 -Wshadow-Wold-style-declaration-Wold-style-definition

当我运行代码时,我得到了 16,900 行的输出:

laaaaa
laaaae
laaaai
laaaao
laaaau
…
lazuza
lazuze
lazuzi
lazuzo
lazuzu

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-08-28
    • 1970-01-01
    • 2011-04-23
    • 1970-01-01
    • 2021-11-29
    • 2011-03-20
    相关资源
    最近更新 更多