Thread: Strings

  1. #1
    Registered User
    Join Date
    Feb 2005
    Posts
    26

    Strings

    Hey, I can't seem to figure this out and have been sitting here for a long time scratching my head. I'm new to programming and I'm trying some stuff out. What I'm trying to do is read in information from a file and the problem I'm having is with the strings. I want to read in names in the format of "<Last Name> <First Name>" but the space between the two totally throws it off. I've searched around looking for a way to read it and couldn't find anything of much help. I did try fgets() but that doesn't seem to work. I've been trying all day to get this to work but can't seem to. Maybe one of you could help.

    Here a sample of an input file, let's call it input.txt
    Code:
    11 5
    Gupta Anil
    96 90 85 90 80  
    Jeffers Jose
    60 0 70 50 30
    Evans Rudy
    80 60 70 50 75
    Williams Jason
    50 40 0 0 70
    Ball Adam
    90 80 60 55 60
    Arnold Joshua
    0 0 0 0 0
    Scot Michael
    80 70 0 0 60
    Cook Bret
    95 80 80 70 60
    Davis Ronald
    0 0 0 0 0
    Fox Brian
    70 60 60 40 50
    Hale Frank
    60 50 60 30 40
    Now for the function, I know it's wrong but it's all I can get.
    Code:
    void get_info(struct students student[], int *num_students, int *exams)
    {
        int i, j, grades = 0;
        char names[30], file[40];
        FILE *infile;
        
        // Get file name 
        printf("Enter the name of the file containing the grades: ");
        scanf("%s", file);
        
        // Open file and read in info 
        infile = fopen(file, "r");
        fscanf(infile, "%d %d", &num_students, &exams);
        
        for(i = 0; i < *num_students; i++)    
        {
            fscanf(infile, "%s", names);
            strcpy(student[i].name, names);
            
            for(j = 0; j < *exams; j++)
            {
                fscanf(infile, "%d", &grades);
                student[i].grade[j] = grades;
            }
        }
        
        // Close file 
        fclose(infile);
    }
    I've tried a lot of different methods but always get the same error.
    Code:
          0 [main] a 3832 handle_exceptions: Exception: STATUS_ACCESS_VIOLATION
      10592 [main] a 3832 stackdump: Dumping stack trace to a.exe.stackdump
    I did however get it working one time but all it did was read in the last name but not the first. Any ideas on how to fix this would be appreciated.

  2. #2
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    > fscanf(infile, "%d %d", &num_students, &exams);
    Remove those &

    With %d, you're supposed to pass a pointer to an int.
    fscanf(infile, "%d", &grades);
    So this is a good example - grades is an int declared locally.

    But exams is already a pointer (you said int *exams), so there is nothing more to do
    So you say
    fscanf(infile, "%d %d", num_students, exams);
    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.

  3. #3
    Registered User
    Join Date
    Feb 2005
    Posts
    26
    Ah, so that's where that error was coming from. I thought it had something to do with the way I was trying to read in the strings. After that I was able to figure out what I wanted to do. At first those two were local variables but I changed them to global after I needed them in other functions. In order to keep the values gotten there I made them pointers but I forgot to remove the address of operators. I probably would have never caught that thanks .

    As for the strings, I figured that out once I got all that cleared up. Here's how I did it, if there's a more effective way, which I'm postive there is, let me know because I'm here to learn . And now the code:

    Code:
    void get_info(struct students student[], int *num_students, int *exams)
    {
    	int i, j, grades = 0;
    	char l_name[30], f_name[30], file[40];
    	FILE *infile;
    	
    	// Get file name 
    	printf("Enter the name of the file containing the grades: ");
    	scanf("%s", file);
    	
    	// Open file and read in info 
    	infile = fopen(file, "r");
    	fscanf(infile, "%d %d", num_students, exams);
    	
    	for(i = 0; i < *num_students; i++)
    	{
    		fscanf(infile, "%s %s", l_name, f_name);
    		strcat(l_name, " ");
    		strcat(l_name, f_name);
    		strcpy(student[i].name, l_name);
    		
    		for(j = 0; j < *exams; j++)
    		{
    			fscanf(infile, "%d", &grades);
    			student[i].grade[j] = grades;
    		}
    	}
    	
    	// Close file 
    	fclose(infile);
    }

  4. #4
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Use fgets() to read a whole line in one go, which would be useful for reading in the student name.

    But watch out for the newline which fgets() will append if there is room for it after reading the line.
    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.

  5. #5
    Registered User
    Join Date
    Feb 2005
    Posts
    26
    Ok, I've run into another problem that's really weird. I'm now trying to sort the names alphabetically. Here's the code I used:

    Code:
    void sort_names(struct students student[], int num_students, int exams)
    {
        int i, count = 0;
        char temp_name[30];
        
        do
        {
            for(i = 0; i < num_students; i++)
            {
                if(strcmp(student[i].name, student[i+1].name) > 0)
                {
                    strcpy(temp_name, student[i].name);
                    strcpy(student[i].name, student[i+1].name);
                    strcpy(student[i+1].name, temp_name);
                }
            }
            
            count++;
        }while(count < num_students);
    }
    But here's the output I get later on in the program:

    Code:
    Here is the sorted list: 
    1.   
    2.   Arnold Joshua
    3.   Ball Adam
    4.   Cook Bret
    5.   Davis Ronald
    6.   Evans Rudy
    7.   Fox Brian
    8.   Gupta Anil
    9.   Hale Frank
    10.  Jeffers Jose
    11.  Scot Michael
    As you can see it's skipping the first number. but the weird thing is if I change this line to:

    Code:
    if(strcmp(student[i].name, student[i+1].name) < 0)
    I get this output:

    Code:
    Here is the sorted list: 
    1.   Williams Jason
    2.   Scot Michael
    3.   Jeffers Jose
    4.   Hale Frank
    5.   Gupta Anil
    6.   Fox Brian
    7.   Evans Rudy
    8.   Davis Ronald
    9.   Cook Bret
    10.  Ball Adam
    11.  Arnold Joshua
    I knew it would do it backwards but why didn't it skip the first one as it did with the > operator? I want it to do what it did here but the way it was in the first output. I don't know why it would work for one but not the other.

    NOTE: Don't mind my function parameters, I'm not done writing the function yet. I'm just trying to get this part to work before I keep writing it.

  6. #6
    Handy Andy andyhunter's Avatar
    Join Date
    Dec 2004
    Posts
    540
    This block of code works fine for me:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void sortList(struct student [], int);
    
    struct student {
        char name[30];
    };
    
    int main(void) {
    
        struct student myList[3];    
        
        strcpy(myList[0].name,"zabba");
        strcpy(myList[1].name,"dog");
        strcpy(myList[2].name,"cat");
    
        for(int i = 0; i < 3; i++) {
            printf("%d. %s\n", i+1, myList[i].name);
        }
    
        sortList(myList, 3);
        
        printf("\n Sorted list\n");
        for(int i = 0; i < 3; i++) {
            printf("%d. %s\n", i+1, myList[i].name);
        }
    
        return 0;
    }
    void sortList(struct student myList[], int numList) {
    
        int count=0, i=0;
        char temp[30];
    
        while(count < numList){
            for(int i = 0; i < numList-1; i++) {
                if(strcmp(myList[i].name, myList[i+1].name) > 0) {
                    strcpy(temp, myList[i].name);
                    strcpy(myList[i].name , myList[i+1].name);
                    strcpy(myList[i+1].name, temp);
                }
            }
            count++;
        }
    }
    Where is your display part of the code?
    Last edited by andyhunter; 02-05-2005 at 05:48 PM.
    i don't think most standard compilers support programmers with more than 4 red boxes - Misplaced

    It is my sacred duity to stand in the path of the flood of ignorance and blatant stupidity... - quzah

    Such pointless tricks ceased to be interesting or useful when we came down from the trees and started using higher level languages. - Salem

  7. #7
    Registered User
    Join Date
    Feb 2005
    Posts
    26
    Here's the whole thing so far:

    Code:
    #include <stdio.h>
    #include <string.h>
    
    struct students
    {
    	char name[30];
    	int grade[5];
    } student[300];
    
    void get_info(struct students student[], int *num_students, int *exams);
    void print_names(struct students student[], int num_students);
    void sort_names(struct students student[], int num_students, int exams);
    
    int main() 
    {	
    	int num_students, exams, option;
    
    	get_info(student, &num_students, &exams);
    	sort_names(student, num_students, exams);	
    
    	do
    	{		
    		printf("Enter 1 to continue the program. Enter 0 to terminate the program.\n");
    		scanf("%d", &option);
    		
    		if(option == 0){
    			printf("\nGoodbye!");
    			return 0;
    		}
    			
    		print_names(student, num_students);
    		
    	}while(option != 0);
    
    	printf("\nGoodbye!");
    	return 0;
    }
    
    void get_info(struct students student[], int *num_students, int *exams)
    {
    	int i, j, grades = 0;
    	char l_name[30], f_name[30], file[40];
    	FILE *infile;
    	
    	/* Get file name */
    	printf("Enter the name of the file containing the grades: ");
    	scanf("%s", file);
    	
    	/* Open file and read in info */
    	infile = fopen(file, "r");
    	fscanf(infile, "%d %d", num_students, exams);
    	
    	for(i = 0; i < *num_students; i++)
    	{
    		fscanf(infile, "%s %s", l_name, f_name);
    		strcat(l_name, " ");
    		strcat(l_name, f_name);
    		strcpy(student[i].name, l_name);
    		
    		for(j = 0; j < *exams; j++)
    		{
    			fscanf(infile, "%d", &grades);
    			student[i].grade[j] = grades;
    		}
    	}
    	
    	/* Close file */
    	fclose(infile);
    }	
    
    void sort_names(struct students student[], int num_students, int exams)
    {
    	int i, count = 0;
    	char temp_name[30];
    	
    	do
    	{
    		for(i = 0; i < num_students; i++)
    		{
    			if(strcmp(student[i].name, student[i+1].name) > 0)
    			{
    				strcpy(temp_name, student[i].name);
    				strcpy(student[i].name, student[i+1].name);
    				strcpy(student[i+1].name, temp_name);
    			}
    		}
    		
    		count++;
    	}while(count < num_students);
    }
    
    void print_names(struct students student[], int num_students)
    {
    	int i;
    
    	printf("\nHere is the sorted list: \n");
    	
    	for(i = 0; i < num_students; i++)
    	{
    		if(i + 1 < 10)
    			printf("%d.   %s\n", i + 1, student[i].name);
    		else if(i + 1 >= 10 && i + 1 < 100)
    			printf("%d.  %s\n", i + 1, student[i].name);
    		else if(i + 1 >= 100)
    			printf("%d. %s\n", i + 1, student[i].name);
    	}	
    }

  8. #8
    Handy Andy andyhunter's Avatar
    Join Date
    Dec 2004
    Posts
    540
    Ok, I compiled and ran this:
    Code:
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    
    void sort_names(struct student student[], int num_students, int exams);
    void print_names(struct student student[], int num_students);
    
    struct student {
        char name[30];
    };
    
    int main(void) {
    
        struct student myList[3];    
        
        strcpy(myList[0].name,"zabba");
        strcpy(myList[1].name,"dog");
        strcpy(myList[2].name,"cat");
    
        for(int i = 0; i < 3; i++) {
            printf("%d. %s\n", i+1, myList[i].name);
        }
    
        sort_names(myList, 3, 5);
        
        printf("\n Sorted list\n");
        
        print_names(myList, 3);
    
        return 0;
    }
    void sort_names(struct student student[], int num_students, int exams)
    {
        int i, count = 0;
        char temp_name[30];
        
        do
        {
            for(i = 0; i < num_students-1; i++)
            {
                if(strcmp(student[i].name, student[i+1].name) > 0)
                {
                    strcpy(temp_name, student[i].name);
                    strcpy(student[i].name, student[i+1].name);
                    strcpy(student[i+1].name, temp_name);
                }
            }
            
            count++;
        }while(count < num_students);
    }
    void print_names(struct student student[], int num_students)
    {
        int i;
    
        printf("\nHere is the sorted list: \n");
        
        for(i = 0; i < num_students; i++)
        {
            if(i + 1 < 10)
                printf("%d.   %s\n", i + 1, student[i].name);
            else if(i + 1 >= 10 && i + 1 < 100)
                printf("%d.  %s\n", i + 1, student[i].name);
            else if(i + 1 >= 100)
                printf("%d. %s\n", i + 1, student[i].name);
        }    
    }
    And still got the correct output. So I believe you have a NULL student in your array somewhere. That would explain why when you sorted alphabetically the first line is blank.
    Last edited by andyhunter; 02-05-2005 at 05:47 PM.
    i don't think most standard compilers support programmers with more than 4 red boxes - Misplaced

    It is my sacred duity to stand in the path of the flood of ignorance and blatant stupidity... - quzah

    Such pointless tricks ceased to be interesting or useful when we came down from the trees and started using higher level languages. - Salem

  9. #9
    Handy Andy andyhunter's Avatar
    Join Date
    Dec 2004
    Posts
    540
    Aha! I think I know where it is being introduced. Instead of :
    Code:
    for(i = 0; i < num_students; i++)
    Use this:
    Code:
    for(i = 0; i < num_students-1; i++)
            {
                if(strcmp(student[i].name, student[i+1].name) > 0)
                {
                    strcpy(temp_name, student[i].name);
                    strcpy(student[i].name, student[i+1].name);
                    strcpy(student[i+1].name, temp_name);
                }
            }
    When doing this kind of sort you only compare up to N-1 values. Give that a try and let me know.
    i don't think most standard compilers support programmers with more than 4 red boxes - Misplaced

    It is my sacred duity to stand in the path of the flood of ignorance and blatant stupidity... - quzah

    Such pointless tricks ceased to be interesting or useful when we came down from the trees and started using higher level languages. - Salem

  10. #10
    Registered User
    Join Date
    Feb 2005
    Posts
    26
    EDIT: I just saw the post above let me try that.

    EDIT: It worked, you were right. Why do you only go up to the N-1?
    Last edited by Pressure; 02-05-2005 at 05:56 PM.

  11. #11
    Handy Andy andyhunter's Avatar
    Join Date
    Dec 2004
    Posts
    540
    Because as you are comparing the values when i = n-1 you are comparing it with value n aka

    Code:
    if(strcmp(student[i].name, student[i+1].name) > 0)
    since i = n-1 therefore

    Code:
    if(strcmp(student[n-1].name, student[n-1+1].name) > 0)
    or more simply

    Code:
    if(strcmp(student[n-1].name, student[n].name) > 0)
    i don't think most standard compilers support programmers with more than 4 red boxes - Misplaced

    It is my sacred duity to stand in the path of the flood of ignorance and blatant stupidity... - quzah

    Such pointless tricks ceased to be interesting or useful when we came down from the trees and started using higher level languages. - Salem

  12. #12
    Registered User
    Join Date
    Feb 2005
    Posts
    26
    Ah, now I understand. If I have anymore problems with the program in the future I'll post it here. Thanks for the help so far .

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Strings Program
    By limergal in forum C++ Programming
    Replies: 4
    Last Post: 12-02-2006, 03:24 PM
  2. Programming using strings
    By jlu0418 in forum C++ Programming
    Replies: 5
    Last Post: 11-26-2006, 08:07 PM
  3. Reading strings input by the user...
    By Cmuppet in forum C Programming
    Replies: 13
    Last Post: 07-21-2004, 06:37 AM
  4. damn strings
    By jmzl666 in forum C Programming
    Replies: 10
    Last Post: 06-24-2002, 02:09 AM
  5. menus and strings
    By garycastillo in forum C Programming
    Replies: 3
    Last Post: 04-29-2002, 11:23 AM