Thread: Input String And Integers From File And Sort By Strings

  1. #1
    Registered User
    Join Date
    Mar 2006
    Posts
    6

    Question Input String And Integers From File And Sort By Strings

    Hi all,

    I'm a beginner at C and I'm currently trying to input a string and 10 integers from a file, and then be able to sort them by the string in ascending order.

    The file looks like this (first string is a place, the next 10 integers are distances)(random numbers I picked by the way :P)

    London 0 23 12 89 456 123 46 732 345 123
    Bath 23 0 46 234 123 46 89 234 567 90

    The distances are relative to each other....

    ie.. London to Bath would be 23 km, which can be read from column 2 on line 1 or first column on line 2

    Now, I can easily input the files and print them using the below code (part of a function) and then using 2 for loops to print them out.

    Code:
    	FILE *openFile;
    	char line[15];
    	char filename[16];
    	char rtn;
    
    	int i, j;
    
    	printf("Please enter the filename of the input file:");
    	gets(line);
    	sscanf(line,"%s%c\n", filename, &rtn);
    	
    	openFile = fopen(filename, "r");
    	
    	if (openFile == NULL)
    	{
    		puts("Error Opening File");
    	}
    
    	for (i = 0; i < 10; i++)
    	{
    		fscanf(openFile, "%s", &theArray2[i]);
    		
    		for (j = 0; j < 10; j++)
    		{
    			fscanf(openFile, "%d", &theArray[i][j]);
    		}
    	}
    }
    Furthermore, I can easily sort the strings in ascending order by the following code:

    Code:
    int comp(const void *str1, const void *str2)
    {
    	return strcmp(str1, str2);
    }
    
    void sortArray(char theArray2[10][11])
    {
    	qsort(theArray2, 10, sizeof(theArray2[0]), comp); 
    }
    BUT... I can't get the integers as described at the beginning of this thread to follow with the strings in order. I've tried using structs (like the one below) using fread in a for loop but i can't get that to work either!

    Code:
    typedef struct{
    	
    	char places[10];
    	int distances[10];
    
    }placedist;
    I've tried a load of things... Just wondering what I can do to solve this problem!!

    Hope you can help,

    xfactor

  2. #2
    Registered User
    Join Date
    Mar 2006
    Posts
    6
    Update:

    I have now managed to get data from the file into an array of structs using:

    Code:
    typedef struct {
    
    	char places[10];
    	int d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
    
    }placedist;
    but I still don't know how to sort the struct according to the string where the integers on each line get sorted aswell

  3. #3
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > int d1, d2, d3, d4, d5, d6, d7, d8, d9, d10;
    This is a backward step from your first attempt of an array.

    > gets(line);
    Use fgets() - see the FAQ

    On sorting
    Code:
    typedef struct{
    	
    	char places[10];
    	int distances[10];
    
    } placedist;
    
    // always gets two pointers to elements of the array
    // eg, the effective call is comp(&theArray[x], &theArray[y] );
    // so first thing is to get the pointers of the right type
    int comp(const void *p1, const void *p2)
    {
    	placedist *a1 = p1;
    	placedist *a2 = p2;
    	// dereference whatever members of the struct you want to compare
    	return strcmp(a1->places, a2->places);
    }
    
    void sortArray(placedist theArray[10])
    {
    	qsort(theArray, 10, sizeof(theArray[0]), comp); 
    }
    If you make a typedef for your
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  4. #4
    Registered User
    Join Date
    Mar 2006
    Posts
    6
    Thanks for the help on sorting. I've gone back to my original first attempt to get the data from the file into an array of structs.

    The for loop below correctly gets the string when using a printf statment but when trying to print the below code as a test, I get some silly number - 536584020:

    Code:
    printf("%d", y[0].distances);
    I've tried using fgets with sscanf but that also does the same thing.

    Below is the struct I'm using and the way I'm getting data from the file.

    Code:
    typedef struct{
    	
    	char places[11];
    	int distances[10];
    
    }placedist;
    
    
    int i;
    
    for (i = 0; i < 10; i++)
    {
    	
    	fscanf(openFile, "%s%d", y[i].places, y[i].distances);
    	
    }
    Hope you can help,

    xfactor

  5. #5
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > fscanf(openFile, "%s%d", y[i].places, y[i].distances);
    You forgot the &

    Use
    gcc -W -Wall prog.c
    To make it tell you when you mess up printf and scanf calls.
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  6. #6
    Registered User
    Join Date
    Mar 2006
    Posts
    6
    Sorry about this but I still can't get it work.... I get some odd numbers printed out

    Code:
    void inputFile (placedist y[10])
    {
    	FILE *openFile;
    
    	int i;
    
    	openFile = fopen("test2.txt", "r");
    
    	for (i = 0; i < 10; i++)
    	{
    		
    		fscanf(openFile, "%s%d", &y[i].places, &y[i].distances);	
    	}
    
    	fclose(openFile);
    
    void printStruct(placedist y[10])
    {
    	int i,x;
    	
    	for (i = 0; i < 10; i++)
    	{
    		printf("%s\t%d\n", y[i].places, y[i].distances);
    	}
    	
    }

  7. #7
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > fscanf(openFile, "%s%d", &y[i].places, &y[i].distances);
    You have one place, and 10 distances
    Code:
    int p, d;
    for ( p = 0 ; p < 2 ; p++ ) {
      fscanf(openFile, "%s", y[p].places ); // note lack of & for a string
      for ( d = 0 ; d < 10 ; d++ ) {
        fscanf(openFile, "%d", &y[p].distances[d] );
      }
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  8. #8
    Registered User
    Join Date
    Mar 2006
    Posts
    6
    Ok thanks, that was a Silly mistake by me there. Printing out fine now.

    The sort also works but there's a slight change I need to add to it.

    See these 2 below, it is how it appears on my screen (other 9 ints are different towns, removed purposely)

    Before sort:
    London 0 23
    Bath 23 0

    After Sort:
    Bath 23 0
    London 0 23

    It reads Bath to bath = 23 miles (because the x co-ords/horizontal are also sorted)

    and London to London = 23 miles

    The end result should be...

    Bath 0 23
    London 23 0.

    I was thinking to do this by moving the 0 along according to where the string has moved to from the sort (to where it's new index is). Is there a way to get the index for the string? and then would I use a swap function?

    I have no idea how to do this in code, I don't know where to start

    Anybody got any ideas?

    This is my code for the sort now by the way:

    Code:
    int comp(placedist *s1, placedist *s2)
    {
    	return strcmp(s1->places, s2->places);
    }
    
    void sortStruct(placedist y[10])
    {
    	qsort(y, 10, sizeof(y[0]), comp);
    }

  9. #9
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > int comp(placedist *s1, placedist *s2)
    Use void* pointers and cast, as per previous posts.
    Otherwise the compiler will complain about mis-matched function types.

    I'm not sure what you mean to do with the distances, but it seems to depend on the relative array indices of the two elements you're comparing.
    You need a global variable of some sort to make this work.
    Code:
    placedist *base;
    int comp(const void *p1, const void *p2)
    {
    	placedist *a1 = p1;
    	placedist *a2 = p2;
    	int i1 = a1 - base;
    	int i2 = a2 - base;
    	int result = strcmp(a1->places, a2->places);
    
    	// do something with base[i1] and base[i2] ?
    	// depending on whether result is < 0, == 0 or > 0
    
    	return result;
    }
    void sortArray(placedist theArray[10])
    {
    	base = theArray;
    	qsort(theArray, 10, sizeof(theArray[0]), comp); 
    }
    If you dance barefoot on the broken glass of undefined behaviour, you've got to expect the occasional cut.
    If at first you don't succeed, try writing your phone number on the exam paper.

  10. #10
    Registered User
    Join Date
    Mar 2006
    Posts
    6
    Sorry about that.

    What I mean is this:

    Before sort:
    London 0 23
    Bath 23 0

    After Sort:
    Bath 23 0
    London 0 23

    When it is sorted, it appear like this: (I have a printHeader Function for the Horizontal variables)

    Code:
    	Bath	London
    Bath	23	0
    London	0	23
    Basically... you can't have bath to bath being 23 miles, it has to be 0.

    Also London to London can't be 23 either, it has to be 0. London to London is the same place.

    I'm trying to figure out a way so it appears like this:

    Code:
    	Bath	London
    Bath	0	23
    London	23	0

    I thought maybe you could swap the values around according to the strings position in the struct array?

    Is that what you meant in your code above? - You've been very helpful with this problem, Sorry to ask you again
    Last edited by xfactor; 03-17-2006 at 12:50 PM.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Reading a file written by VB
    By nemaroller in forum C++ Programming
    Replies: 8
    Last Post: 07-12-2002, 11:17 PM