Click here to Skip to main content
15,884,176 members
Please Sign up or sign in to vote.
1.00/5 (1 vote)
See more:
I use the fsanf() command in C to open and read a text file that contains only two lines. in first line is an integer N number, and in the second line is the N integer numbers that the first line says.

Eg.
-------------- nubmers.txt --------------
8                                       <-- we want 8 numbers for the 2nd line
16 8 96 46 8 213 5 16                   <-- and we have 8 numbers! :)


Also if the second line have more or less numbers than the first line integer says will print an error:

Eg
-------------- nubmers.txt --------------
10
16 8 96 46 8 213 5 16 8 9 21 5 69 64 58 10 1 7 3 6



Now I will post the fscanf() code:
C++
int num;

...

fscanf(fp,"%d",&num);
int i = 0;                                                      
int value = 0;                                                 

while (fscanf (fp, "%d", &value) == 1)         
{
    i++;                                                            
}

if (i > num)                                                  
{
    printf ( "too many integers\n");                                
    getchar();                                                      
    return 1;                                                       
}

if (i < num)                                                 
{
    printf ("not enough integers\n");                              
    getchar();                                                     
    return 1;                                                       
}

// if i equals num the code will get to this spot and will continue the debugging!

printf("work until now");                                       
getchar();                                                     
return 0;


But the problem is this.
Lets say that we want 4 numbers for the second line. And In the second line we have 3 numbers and 1 letter.

Eg
XML
-------------- nubmers.txt --------------
4
3 2 1 p



Then the code will read the letter and it'll show that we have less integers. -cause the letter p isn't a integer.
I want to get an error message that will say we have a letter in the text file and not a number
Posted
Updated 5-Oct-14 6:00am
v3
Comments
George Jonsson 5-Oct-14 11:57am    
Your code doesn't make much sense to be honest.
[no name] 5-Oct-14 12:00pm    
do I need to change something?
George Jonsson 5-Oct-14 12:06pm    
Well, what is the purpose of the code? To validate the text file or to read the contents?
Right now your while loop doesn't take care of the values read.
And you could put the if statements inside the loop.
[no name] 5-Oct-14 12:10pm    
How exactly should I put the if statements to be the programm more flexible?
Sergey Alexandrovich Kryukov 5-Oct-14 14:09pm    
A language like C is not made of "commands"... Do you understand what is language and what is library..?
—SA

Check out the fscanf[^] return value.
C
...
int success = 1;
for(int i = 0; success && (i < num); ++i)
{
    if (fscanf(fp, "%d", &value))
    {
        // store value somewhere
        // ...
    }
    else
    {
        printf("failed to read value or too little values");
        success = 0;
    }
}
if (success && fscanf(fp, "%d", &value))
{
    printf("too many values");
}
...

Cheers
Andi
 
Share this answer
 
Comments
CPallini 5-Oct-14 15:56pm    
5.Sorry I 'updated' (I didn't change anything) your solution by mistake.
Andreas Gieriet 5-Oct-14 17:08pm    
No problem ;-)
Thanks for your 5!
Cheers
Andi
In order to do what you want you should not read the values via fscan's %d format, but just tokenize the string, i.e. subdivide it into strings. You can do that with fscan's %s format, although I would prefer other means. So your loop could look like:
C++
// improved code, but not really good; see below
char str[100];
int value;

while (fscanf (fp, "%s", &str) == 1)         
{
    if (sscanf (str, "%d", &value) == 1)
        i++;
    else
        printf ("Input <%s> is not a number", str);
}

There are two reasons, why I don't like the scanf functions: For one they offer no control over handling newlines. A newline is just another whitespace character. So if your input would be
5
12 56 89
34 52

it would be regarded as legal input. The second reason is that is inherently unsafe, as you cannot specify the length of your input buffer for the %s format (I put in 100 in the example above).

As an alternative to scanf I would prefer to first read the input line by line with fgets. Then parse the line by strtok, and finally convert it to integers by strtol.
 
Share this answer
 
C#
#include "stdafx.h"

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


char  *fname ="E:\\00-C++\\VC2010\\PROJEKTE\\testfile.txt"; //filepath with the numbers
const int   first_min       =3;  //min number count for line 2
const int   first_max       =12; //max number count for line 2
      int   first_number    =0;
const long  second_min      =100;
const long  second_max      =1000000;

const int   max_linelength  =100;  // make sure that real file-line-length is shorter than max_linelength
      char  line[max_linelength+5];
      int   lineno          =0;

      long  number[first_max+5];
      int   ixnumber        =0;

//--------------------------------------------------------------------------------
void funcPrintRuler()
{
  printf("\n");
  printf("\n.........1.........2.........3.........4.........5.........6.........7.........8.........9");
  printf("\n123456789012345678901234567890123456789012345678901234567890123456789012345678901234567890");
}

//--------------------------------------------------------------------------------
int funcOnlyDigitsOrSpaceAllowed(int lineno,char *line)
{
  int   kzdigit =0;
  int   pos     =0;
  char  *p      =line;

  while (NULL!=*p)
  {
    pos++;
    if (isdigit(*p))  {kzdigit=1;p++;continue;}
    if (' '==*p)      {p++;continue; }

    funcPrintRuler();
    printf("\n%s",line);
    printf("\n%d.line: Only digits or space allowed. pos=%d",lineno,pos);
    printf("\n");
    return 0;
  }

  if (0==kzdigit)
  {
    funcPrintRuler();
    printf("\n%s",line);
    printf("\n%d.line: digits are missing",lineno);
    printf("\n");
    return 0;
  }
  return 1;
}

//--------------------------------------------------------------------------------
void funcGetNumbers(int lineno,char *line)
{
  char  *p  =line;
  ixnumber  =0;

  while (NULL!=*p )
  {
    if (ixnumber>=first_max) return ; // too many numbers
    if (' '==*p) {p++; continue;}

    number[ixnumber]=atol(p);
    while( NULL!=*p && isdigit(*p))  {p++; continue;} // goto next number
    ixnumber++;
    p++;
  }
}

//--------------------------------------------------------------------------------
int funcCheckLine1(int lineno,char *line)
{
  funcGetNumbers(lineno,line);
  if (1!=ixnumber )
  {
    printf("\n%d.line=%s<",lineno,line);
    printf("\nonly one number allowed");
    return 0;
  };

  if ( number[0]<first_min || number[0]>first_max )
  {
    printf("\n%d.line=%s<",lineno,line);
    printf("\n%d.line contains number=%d,  but must be >=%d and <=%d",lineno,number[0],first_min,first_max);
    return 0;
  }
  return 1;
}

//--------------------------------------------------------------------------------
int funcCheckLine2(int lineno,char *line)
{
  int i;
  funcGetNumbers(lineno,line);
  if (ixnumber!=first_number )
  {
    printf("\n%d.line=%s<",lineno,line);
    printf("\nnumber count=%d, but must be %d",ixnumber, first_number);
    return 0;
  };
  for(i=0; i<ixnumber;i++)
  {
    if (number[i]<second_min || number[i]>second_max )
    {
      printf("\n%d.line=%s<",lineno,line);
      printf("\nnumber %d=%d, but must be >=%d and <=%d",i+1,number[i],second_min,second_max);
      return 0;
    }
  }
  return 1;
}

//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
//--------------------------------------------------------------------------------
int main(int argc, char *argv[])
{
  int   i;
  FILE  *fp;
  int   lg=0;

  printf("START");
  
  fp = fopen (fname, "r");
  if (fp == NULL) { printf ("Cannot open: \n%s",fname); goto w_err;}

  while (NULL != fgets(line, max_linelength, fp))
  {
    lineno++;
    lg=strlen(line);
    line[lg-1]='\0'; // remove '\n', only for printf line, not nessessary for read numbers
    //printf("\n%d. line=%s<",lineno,line);

    switch( lineno )
    {
      case 1:
        if ( !funcOnlyDigitsOrSpaceAllowed(lineno,line) ) goto w_err;
        if ( !funcCheckLine1(lineno,line) )               goto w_err;
        first_number=number[0];
      break;
      case 2:
        if ( !funcOnlyDigitsOrSpaceAllowed(lineno,line) ) goto w_err;
        if ( !funcCheckLine2(lineno,line) )               goto w_err;
      break;
      default:
        // do something
        printf("\n%d.line=%s<",lineno,line);
    }
  }
  fclose (fp);


w_ok:
  printf("\n\nFile Content:");
  printf("\nline 1 read %d=number count for line 2",first_number);
  for (i=0; i<ixnumber; i++)
  {
    printf("\nline 2 read %d.number=%ld",i+1,number[i]);
  }
  printf("\nprogram OK");

  getc(stdin); // only pause
  exit(EXIT_SUCCESS);

w_err:
  printf("\nprogram error");
  getc(stdin);
  exit(EXIT_FAILURE);
}
 
Share this answer
 
v4

This content, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)



CodeProject, 20 Bay Street, 11th Floor Toronto, Ontario, Canada M5J 2N8 +1 (416) 849-8900