使用scanf读取C编程中的文本

时间:2016-09-19 08:00:44

标签: c scanf

这是我的C编程课,我的老师正在使用scanf,我们不能使用其他任何东西。我正在传递这个文本文件:https://gist.github.com/cjoshmartin/29bd3365a925ee295da21ae2e917c7e1 我正在使用推荐行传递文件与此推荐: program1< lab4text.txt

here is what I am trying to get for output:

   | SSN   |   Average   |  263? |
   ‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐‐
1  | xxxx  |   xx.xxx%   |   Y   |
2  | xxxx  |   xx.xxx%   |   N   |
3  | xxxx  |   xx.xxx%   |   Y   |
4  | xxxx  |   xx.xxx%   |   Y   |



here is  what is what I currently am getting:
   |  SSN | Average |  263 |
-------------------------
 1  | 2381  | 67.454 %  |     Y |
 2  |    0  | -167.040 %  |     2 |
 3  |    0  | 3762321554297869312.000 %  |     6 |
 4  | 1234  | 81.318 %  |     Y |

我认为scanf正在从文本文件的错误部分读取,但我不知道如何修复它。

这是我目前的代码:

#include <stdio.h>
 void main(void){

//FILE *file;
int i = 0;
int SSN[4] = { 0 }, j;
char isin263[4];
float quizavg[4];
float labavg[4];
float exam1[4];
float exam2[4];
float finalexam[4];
scanf("%*[^\n]\n");
scanf("%*s %*s %*s %*s %*s %*s %*s %*s %*s %*s %*s");
scanf("%*[^\n]\n");


for (i = 0;i < 4;i++)
{
    scanf("%*s %*s %*s");
    scanf("%*d-%*d-%d", &SSN[i]);
    scanf(" %*9s%*c%*c%*c%*c %c %f %f %f %f %f\n", &isin263[i], &quizavg[i], &labavg[i], &exam1[i], &exam2[i], &finalexam[i]);
}


    printf("|%5s | %5s | %4d |\n","SSN","Average", 263);
    printf("-------------------------\n");
    for (j = 0;j < 4;j++)
    {
        //fixed this line
        printf(" %i  | %4d  | %5.3f %%  | %5c |\n",j+1,SSN[j], (quizavg[j]*0.07)+(labavg[j]*0.24)+((exam1[j]+exam2[j])*0.185)+(finalexam[j]*0.32), isin263[j]);
    }


  }

任何帮助将不胜感激!

2 个答案:

答案 0 :(得分:2)

如果您打算尝试使用fscanf读取不同的数据,那么格式字符串将是您成功(或失败)的关键。如果您需要收集的每一行都具有相同的格式,那么您可以尝试使用fscanf读取数据(同时通过使用fgets将读取与解析和解析相关联来获得灵活性和sscanf)。但是,只要您有办法保留所需的行,并跳过那些不需要的行,那么fscanf可用作工具。

在这种情况下,您的示例数据LYF_HKN在他的答案中做得很好,因为会计所需的每一行中的所有信息。我只想添加一个小变体并使用类似的东西:

char *fmt = " %*[^\"]\"%[^,], %[^\"]\" %s %s %[YN] %lf %lf %lf %lf %lf";

其余的只是循环输入文件中的行并索引添加到结构中的学生。您需要捕获return的{​​{1}}并将其与fscanf所需的匹配计数进行比较,以验证您的每个值是否已收到输入。您还需要跳过标题行和任何其他不包含学生数据的行。只要10没有遇到fscanf在流上设置错误条件,您就可以通过阅读来完成此操作。然后,您只需针对预期的EOF检查匹配计数return),以表明它是否是有效的学生数据行。

将它们放在一起,您可以执行以下操作:

10

使用#include <stdio.h> /* constants for use in your code */ enum { YN = 2, DOB = 11, SS = 12, NM = 32 }; typedef struct { char last[NM], first[NM], ss[SS], dob[DOB], yn[YN]; double qavg, lavg, ex1, ex2, fex; } stnt; int main (int argc, char **argv) { stnt s[8] = {{ .first = "" }}; int cnv = 0, n = 0; char *fmt = " %*[^\"]\"%[^,], %[^\"]\" %s %s %[YN] %lf %lf %lf %lf %lf"; FILE *fp = argc > 1 ? fopen (argv[1], "r") : stdin; if (!fp) { /* validate file open for reading */ fprintf (stderr, "error: file open failed '%s'.\n", argv[1]); return 1; } /* read each line, if the match-count is 10 increment index */ while ((cnv=fscanf (fp, fmt, s[n].last, s[n].first, s[n].ss, s[n].dob, s[n].yn, &s[n].qavg, &s[n].lavg, &s[n].ex1, &s[n].ex2, &s[n].fex)) != EOF) if (cnv == 10) n++; if (fp != stdin) fclose (fp); /* close file if not stdin */ for (int i = 0; i < n; i++) /* output the student information */ printf ("\n student : %s %s\n ss number : %s\n D.O.B. : %s\n" " yes/no : %s\n quiz avg : %.2lf\n lab avg : %.2lf\n" " exam 1 : %.2lf\n exam 2 : %.2lf\n final : %.2lf\n", s[i].first, s[i].last, s[i].ss, s[i].dob, s[i].yn, s[i].qavg, s[i].lavg, s[i].ex1, s[i].ex2, s[i].fex); return 0; } fgets

鉴于有关sscanffgets的使用的讨论和评论,除了{{1}之外,值得使用我更喜欢的方法的简短示例例子。代码大致相同,只是添加了一个缓冲区sscanf来保存用户输入行,并根据fscanf的返回值控制循环。除此之外,用buf替换fgets只不过是用缓冲区代替fscanf调用中的文件流。 sscanfsscanf都会返回匹配计数,它是根据中提供的转化说明符发生的成功转化次数格式字符串

fscanf

示例使用/输出

使用您的数据(使用其中任何一种),您最终会得到类似于以下内容的输出:

sscanf

答案 1 :(得分:1)

也许this是您正在寻找的。

scala> import ml.dmlc.xgboost4j.scala.spark.XGBoostEstimator
import ml.dmlc.xgboost4j.scala.spark.XGBoostEstimator

scala> val xgb = new XGBoostEstimator("features", "label", Map.empty,10, 2)
This is null
xgb: ml.dmlc.xgboost4j.scala.spark.XGBoostEstimator = XGBoostEstimator_6cd31d495c8f

scala> xgb.uid
res1: String = XGBoostEstimator_6cd31d495c8f