0

I am having a bit of difficulty understanding the arguments for fscanf. The first two are self-explanatory. The first argument is the point file. It gets the content from this file. The second argument is the type of content in the file. In this case it's int so there is usage of %d. Now, the third argument, I am having difficulty discerning and it would help to have it done in some other way, so I can better understand what this 3rd argument is all about.

#include <stdio.h>
#include <string.h>
int main(void);

void getCode(char a[]);
int getMessage(int a[]);
void sortMessage(int a[], int b);
void decodeMessage(char a[], int b[], int c);

int main(void) {
  // declare file names

  char string[53];
  int integers[27];
  int msgSize;
  // int codeSize = 52;

  // Open files & there content
  getCode(string);
  msgSize = getMessage(integers);
  sortMessage(integers, msgSize);
  decodeMessage(string, integers, msgSize);
}

void getCode(char string[]) {
  // get content from code file & print it
  FILE *C = fopen("codefile.txt", "r");

  while (fgets(string, 55, C)) {
    printf("%s\n", string);
  }
}

getMessage(int integers[]) {
  // Get content from message file & return it
  FILE *M;
  M = fopen("msgfile.txt", "r");

  int counter = 0;

  /* Read one number at a time from the file and store it */
  while (!feof(M)) {
    fscanf(M, "%d", (integers + counter));
    counter++;
  }

  /* Close the file */
  // fclose(M);

  return (counter);
}
Bill Lynch
  • 80,138
  • 16
  • 128
  • 173
  • 4
    `integers+counter` is the same as `&integers[counter]`. You could declare a variable, e.g. `int temp;` and then `fscanf(M, "%d", &temp);` followed by `integers[counter] = temp;` Regardless of how you manage that part of the code, you need to realize that [`while(!feof(fp))` is always wrong](https://stackoverflow.com/questions/5431941). – user3386109 May 06 '21 at 02:00
  • 1
    You don't need to understand _any_ of the arguments to `fscanf`, because [the `*scanf` functions are broken as designed and should not be used at all](https://stackoverflow.com/questions/58403537/what-can-i-use-for-input-conversion-instead-of-scanf). What you need to understand is what to use instead: usually the first thing to try is some combination of `fgets`, `strsep`, and the `strto*` functions. – zwol May 06 '21 at 02:09
  • Avoid size mistakes: `char string[53]; ... fgets(string, 55, C)` --> `fgets(string, sizeof string, C)` – chux - Reinstate Monica May 06 '21 at 02:17
  • In your specific case, `fscanf(M, "%d", &integers[counter]);` is equivalent, but fix `while (!feof(M))` and you cannot use any input function correctly unless you ***check the return***. E.g. `while (fscanf(M, "%d", &integers[counter]) == 1) counter++;` – David C. Rankin May 06 '21 at 03:54

1 Answers1

0

The third, and subsequent parameters if used, are pointers to the destinations of the parsed values. The better way to write that is &arrayname[index] because it more clearly indicates you are using a type size array index as a pointer. Note that newlines are just like any other whitespace. Try this yourself

Single Example :

#include <stdio.h>
void main()
{
    int count=3;
    int ints[3];
    
    printf("Give me %d:\n",count);
    for (int i=0;i<count;i++)
        scanf("%d",&ints[i]);
    
    printf("You said:\n");
    for (int i=0;i<count;i++)
        printf("%d\n",ints[i]);
}

Result:

Give me 3:                                                                                                                                                                                                                       
12                                                                                                                                                                                                                               
23                                                                                                                                                                                                                               
34                                                                                                                                                                                                                               
You said:                                                                                                                                                                                                                        
12                                                                                                                                                                                                                               
23                                                                                                                                                                                                                               
34                                                                                                                                                                                                                               
    

Multiple Example: (which could allow you to mix types, or fork into more arrays).

#include <stdio.h>

void main ()
{
  int count = 6;
  int ints[6];

  printf ("Give me %d :\n", count);
  for (int i = 0; i < count; )
    { 
      int got;
      got= scanf ("%d %d %d", &ints[i], &ints[i + 1], &ints[i + 2]);
      i+= got;
    }
        
  printf ("You said:\n");
  for (int i = 0; i < count; i ++)
    printf ("%d\n", ints[i]);
}

Result:

Give me 6 :                                                                                                                                                                                                                      
1 2 3                                                                                                                                                                                                                            
4                                                                                                                                                                                                                                
5 6                                                                                                                                                                                                                              
You said:                                                                                                                                                                                                                        
1                                                                                                                                                                                                                                
2                                                                                                                                                                                                                                
3                                                                                                                                                                                                                                
4                                                                                                                                                                                                                                
5                                                                                                                                                                                                                                
6    
gcycle7
  • 26
  • 2
  • If all you do with the return is `i+= got;` -- how do you handle a *matching-failure*? Character extraction ceases at the point of failure leaving the offending characters in `stdin` *unread* just waiting to cause the next attempt to fail. You need to use the return as something more than a way to control the increment of `i` -- otherwise, you have just written an infinite loop in the case of a matching-failure. – David C. Rankin May 06 '21 at 03:57
  • The got is just for explanation. I tested it, and I don't think it works like you say. It does not return until it gets 3, regardless of newlines. So yea, it will ask forever. – gcycle7 May 06 '21 at 04:08
  • What happens if the user slips reaching for `'4'` and types `'r'` by mistake in your `"Give me 6 :"` example? – David C. Rankin May 06 '21 at 04:19
  • I see your point, it loops forever, because it will never consume those bad characters. – gcycle7 May 06 '21 at 04:32
  • Yep, that's why you either control your read-loop with the return, or handle the failure by emptying `stdin` before the next attempted read (and is also whey reading with `fgets()` and then parsing the numbers with `sscanf()` is the preferred way) When you use `fgets()` you consume a line-at-a-time regardless what happens in the conversion `:)` Similar [How to use sscanf to read a line into 5 variables](https://stackoverflow.com/a/42017403/3422102) – David C. Rankin May 06 '21 at 04:34