-1

Hi i am trying to store fscanf into a data type in order to print it in reverse manner but cannot get it done.

here is my code

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

int main(int argc, char *argv[])
{
    FILE* input;
    FILE* output;

    input = fopen(argv[1],"r");
    output = fopen(argv[2],"w");

    int zipcode, population;
    while(fscanf(input,"%d %d\n",&zipcode, &population)!= EOF)
    {
        fwrite(&population, sizeof(int), 1, output);
    }
    return 0;
}

here is what i have been trying to do

for(i = fscanf(input,"%d %d\n",&zipcode, &population); i!=EOF; i++)
    {
        fwrite(&population, sizeof(int), 1, output);
    }
Jordan
  • 5
  • 3
  • I feel you should using `fprintf` instead of `fwrite` i.e. use `fprintf(output, "%d\n", population);`. Also, after the `while` loop terminates, you should close the `FILE` pointers as a good programming habit. – Ganesh Mar 24 '13 at 04:09
  • but that wont still print it in reverse order @Ganesh – Jordan Mar 24 '13 at 04:10
  • how will you store a fscanf to somthing else like and int (if possible) @Ganesh – Jordan Mar 24 '13 at 04:10
  • @user2203801.. by reverse order, do you mean if the population is 123456, your print should be 654321 ? – Ganesh Mar 24 '13 at 04:11
  • this is an little endian to big endian conversion, so i am trying to print the data out, the above function wrks for little endian but how do i reverse the order since reverse order is big endian so i have number that get converted to binary dump @Ganesh – Jordan Mar 24 '13 at 04:13
  • @Ganesh you can say so that yes its 1234 but i need to print if 4321 using the same program – Jordan Mar 24 '13 at 04:15
  • 1
    I think this link http://stackoverflow.com/questions/2182002/convert-big-endian-to-little-endian-in-c-without-using-provided-func might be useful – Ganesh Mar 24 '13 at 04:27
  • Please clarify this question: Is it about endianness conversions, or about reversing integer numbers and/or strings? These are quite different beasts: the former has to do with binary representations of data types and the latter has to do with modifying the data itself. – SeKa Mar 24 '13 at 05:08
  • Then I'd recommend Ganesh's link above in comments (the SO link re: endianness). Another possibility might be to leverage the idea that network byte order is big-endian, so the htonl()/htons() class of functions might do the work for you... – SeKa Mar 24 '13 at 05:18

3 Answers3

1

I think you've missed the point of fscanf (to provide portable and machine-independent data input) by unportably outputting the machine-dependent, internal representation of an int on your system.

How would you get the '2' out of 200? 200 / 100 results in 2. Is this any different to getting the '2' out of 256?

How would you get the '5' out of 256? Have you ever used the modulo (%) operator to obtain the remainder of a division? 256 % 100 results in 56. 56 / 10 results in 5.

What about the '6'? How would you swap the 6 and the 2? Presuming you've used the algorithm above to extract the 2 into a "multiples of one hundred" column, and the 6 into a "multiples of one" column, couldn't you swap them so that the 6 lies in the "multiples of one hundred" column and the two lies in the "multiples of one" column? You can use this approach to portably output in little endian, big endian or whatever mixed endianness you like... and there's a reverse approach to portably input in little endian, big endian or whatever mixed endianness you like. Can you work it out?

How would you get the 0x1f out of 0x1f23? How do you get the 0x23 out of that number? Interestingly, you can extract these "bytes" (octets, technically) using the same approach (division and modulo), but a different base: 0x100 instead of 10, 0x10000 instead of 100, 0x1000000 instead of 1000, etc. In fact, this is true for most number systems: binary, octal, decimal, hexidecimal... Perhaps a more interesting experiment might be implementing portable base negative two input/output, for both LSB (least significant bit first) and MSB (most significant bit first).

edit: In fact, there's a simpler way to achieve the result you've described in your comments: Obtain your integer modulo ten, and print that as a decimal digit. Then divide your integer by ten and continue with this number as your integer. Repeat these two steps until your integer is zero.

autistic
  • 1
  • 3
  • 35
  • 80
  • i understand that, but how will that help me reversing the binary dump? – Jordan Mar 24 '13 at 04:42
  • There is no significant reason to write code that relies upon the internal representation of integers (eg. `fwrite(&population, sizeof(int), 1, output);`. Doing so can result in undefined behaviour (and to others: if you want a debate about this, please do so on comp.lang.c or ##C freenode where people *know the standard* and don't mind if there's a long debate). What do you want? Big endian, or little endian? I don't see this specified in your question. Since specifying the base is a prerequisite to endianness, we need that, too! Don't confuse *binary* (0's and 1's) with your machine (0..255) – autistic Mar 24 '13 at 05:36
  • @Jordan Once you specify the base (probably base 256, big endian meaning the first 0-255 "digit" is the largest), you can start talking about rearranging place values (eg. swapping the place value representing multiples of `1` with the place value representing multiples of `256 * 256 * 256`), and then you can specify the conversion from *big endian* to *little endian* in terms of an actual algorithm. – autistic Mar 24 '13 at 05:38
1

To print you data in revers for example population = 123456 you want to printf like 654321. simple way is: read population in a string instead a int. and define strrev() function to print string in reverse

As I understand from your comments your file is a sequence of zipcode and population something like:

 46804 3450103 37215 1337 47906 46849

and you want to write alternative numbers back to some output file, do like this(read comments to understand code):

#include<stdio.h>
#include<string.h>
#define SIZE 50
void strrev(char* st) {// string reverse function()
  char* f = st;      // points to first
  char* l = st + strlen(st) -1;  // points to last char
  char temp;  
  while(f < l){
    // swap two chars in string at f & l memory
    temp = *f;
    *f = *l;
    *l = temp;

    f++;
    l--;
  }
}
int main(int argc, char* argv[]){
    if(argc!=3) return 0;
    FILE* input  = fopen(argv[1],"r");
    FILE* output  = fopen(argv[2],"w");
    int zipcode;
    char population[SIZE] = {0};
    while(fscanf(input,"%d %s\n",&zipcode, population)!= EOF){
        // population is always alternative number 
          strrev(population);    // reverse the string 
        //printf("%s\n",population);
          fprintf(output,"%s ",population);  // write in output file
    }
    return 1;
}

And this works as follows:

:~$ cat inputfile 
 46804 3450103 37215 1337 47906 46849
:~$ ./a.out  inputfile outputfile
~$ cat outputfile 
3010543 7331 94864

This is one kind of simple solution.

EDIT Because you are commenting you need binary dump file. So I think you need outfile in binary formate: Just open output file in binary mode and use write function. For this I am writing a partial code(again read comments):

FILE* output  = fopen(argv[2],"wb");  
    //                             ^  open in write binary mode
int val;   // an extra variable int
while(fscanf(input,"%d %s\n",&zipcode, population)!= EOF){
      strrev(population);   // revers string        
      val = atoi(population);  // convert strint to int
      fwrite(&val,sizeof(int),1,output); // write in binary file
}
Grijesh Chauhan
  • 57,103
  • 20
  • 141
  • 208
  • my input file is somthing like this 46804 3450103 37215 1337 47906 46849 (i just need to read 3450103, 1337,46849). given that i need to convert it to binary dump. will this work if i use fwrite, since i have to use the to write to an output file – Jordan Mar 24 '13 at 05:01
  • sorry about this, i pressed enter by mistake – Jordan Mar 24 '13 at 05:03
  • @Jordan read updated answer – Grijesh Chauhan Mar 24 '13 at 06:12
0

To convert endianess, you could refer to this link: convert big endian to little endian in C [without using provided func]

Else, you could refer to the function below as an example

int convert_endian(int n)
{
    int num = 0;
    while(n > 0) {
        num = (num * 10) + (n %10);
        n = n / 10;
    }
    return num;
}
Community
  • 1
  • 1
Ganesh
  • 5,880
  • 2
  • 36
  • 54