Code Newbie
News     Forums     Search     Members     Sign Up    

My Code Newbie
Username

Password

Articles/Snippets
ASP Classic
ASP.NET
C
C#
C++
HTML / CSS
Java
Javascript
Linux / BSD
Perl
PHP
Python
Ruby
SQL
VB 6
VB.NET

C.N. Friends
  Planet Rome

Link to Us!
Code Newbie
  Code Newbie
    forums
Old 03-23-2005, 09:58 PM   #1 (permalink)
JaySun
Registered User
 
Join Date: Mar 2005
Posts: 7
JaySun is on a distinguished road
File I/O and arrays

Having some difficulties with concept of moving strings from a file into an array in C.
The txt file my program is reading from looks like this:
Karen Smith 100 100 100 100 100
John Oliver 78 90 64 51
Henry Green 44 55 44 44

The goal is to read the first names and store in array, read last names store in a second array and then read the scores and store in a third array. The first two arrays are to have 50 columns and N rows. I created this code to just handle the first name array (fname) and to print the values of array on the screen so I can ensure that the array is taking in the proper values.

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

int main (void)

{
	int N, i, j;
	FILE *ifp, *ofp;
	char **fname, **lname, *grades;
	float **scores;
	
	printf ("How many records do you have?\n");
	scanf  ("%d", &N);
	
	ifp = fopen ("input.txt", "r");
	if (ifp == 0)
		{
			printf ("\nNot able to open file!");
			return 0;
		}
	else
		  for (i = 0; i < N; ++i)
			 for (j = 0; j <50; ++j)
		   	fscanf (ifp, "%s", fname);
		
		
		for (i = 0; i < N; ++i)
			for (j = 0; j < 50; ++j)
			printf ("%s", fname[i][j]);
			printf ("\n");
	
		
	return 0;
}
During runtime I get the following errors that occur after user is prompted to enter number of records.
0 [main] a 3000 handle_exceptions: Exception: STATUS_ACCESS_VIOLATION
6148 [main] a 3000 stackdump: Dumping stack trace to a.exe.stackdump

Very confused on whole topic of scanning characters from a file into an array. If anyone can comment on code or provide link for online info in general I would apreciate it.

Last edited by JaySun; 03-23-2005 at 09:59 PM. Reason: Left out language
JaySun is offline   Reply With Quote
Old 03-23-2005, 11:48 PM   #2 (permalink)
redhead
Newbie
 
redhead's Avatar
 
Join Date: Jun 2002
Location: Denmark
Posts: 1,695
redhead is on a distinguished road
Code:
...
	FILE *ifp, *ofp;
	char **fname, **lname, *grades;
	float **scores;
	...
	  for (i = 0; i < N; ++i)
			 for (j = 0; j <50; ++j)
		   	fscanf (ifp, "%s", fname);
		
		
		for (i = 0; i < N; ++i)
			for (j = 0; j < 50; ++j)
			printf ("%s", fname[i][j]);
			printf ("\n");
...
There are some flaws in this, you can't read into a char** without having allocated the needed memory, this will produce random behaviour from your program.

I'll work on a solution in a minut, I just gotta get some breakfast now.
__________________
Don't worry Ma'am, We're university students, We know what We're doing.
-----
If you pull the pin, Mr.Grenade would no longer be your friend.
-----
01000111 01101111 00100000 01000011 00100000 00100001
redhead is offline   Reply With Quote
Old 03-24-2005, 12:31 AM   #3 (permalink)
JaySun
Registered User
 
Join Date: Mar 2005
Posts: 7
JaySun is on a distinguished road
When I started this program originally (I started all over again in frustration) I had set this up to deal with the array sizes.
Code:
  fname = (char**) calloc (N, sizeof (char*));
  	for (i = 0; i < N; ++i)
		fname[i] = (char*) calloc (50, sizeof (char));
  lname = (char**) calloc (N, sizeof (char*));
  	for (i = 0; i < N; ++i)
		lname[i] = (char*) calloc (50, sizeof (char));
  scores = (float**) calloc (N, sizeof (float*));
  	for (i = 0; i < N; ++i)
		scores[i] = (float*) calloc (4, sizeof (float));
  grades = (char*) calloc (N, sizeof (char));
Does this look correct? Thanks for the help...Hope you enjoyed breakfast.
JaySun is offline   Reply With Quote
Old 03-24-2005, 02:30 AM   #4 (permalink)
redhead
Newbie
 
redhead's Avatar
 
Join Date: Jun 2002
Location: Denmark
Posts: 1,695
redhead is on a distinguished road
Yes, those alterations does some of the right things here, you're allocating the memory needed.
But what do you know about the scores ? aren't there supposed to be unlimited number of scores per person in the list ?
And where do the grades come from ?? I dont see any of that mentioned in your input.txt file...
Or are they something the teacher should type in, according to the output given by the program, when listing every student with theyre apropriate scores ?
But then, where should the program store that info ?


I have to attend a family easter dinner, but later tonight, when thats over, I'll have a working example ready.
__________________
Don't worry Ma'am, We're university students, We know what We're doing.
-----
If you pull the pin, Mr.Grenade would no longer be your friend.
-----
01000111 01101111 00100000 01000011 00100000 00100001
redhead is offline   Reply With Quote
Old 03-24-2005, 09:20 AM   #5 (permalink)
JaySun
Registered User
 
Join Date: Mar 2005
Posts: 7
JaySun is on a distinguished road
The teacher is to enter each students name along with 4 scores for each student. Somewhere in the program it should take those 4 scores sum them up and divide by 4. Each number score is evaluated and assigned a letter grade (A = 90-100, B = 80-90, etc)....These letter grades are to be stored in array grades. In the end the program should print each students first and last name and letter grade on the screen. Then this is printed to file "output.txt". There is actualy a menu that the user will be prompted with :
1) Read student's records
2) Compute Greades
3) Display Grades
4) Store Grades
5) Quit
Sorry I have not mentioned this but I was mostly concerned with allocating the needed memory for each array, reading from the file and storing the data into the array. That should be the whole program in a nutshelll above.
JaySun is offline   Reply With Quote
Old 03-24-2005, 03:02 PM   #6 (permalink)
redhead
Newbie
 
redhead's Avatar
 
Join Date: Jun 2002
Location: Denmark
Posts: 1,695
redhead is on a distinguished road
Ok, I'm back, and I'm drunk.. So please take this with a grain of salt.
I've got a working example, it will read your input.txt file, and show you what it found in it.. I didn't oncorporate the desired functioanlity, but on teh other hand, this will take an unlimited number of students, with an unlimited number of grades per student.. What you decide to do with it si entirely up to you..

The code is base on a lot of pointer arritmetic, which at some points might seem obscure, but if you dont know what the h*** it is doing, then feel free to question that part, I might be sober nough tomorrow to even answer a qustion like that.. Or I might have fogotten why I did it in the first place...
Code:
#include <stdio.h>    // printf(), fope(), fgets(), fclose()
#include <stdlib.h>   // malloc(), free(), atoi()
#include <string.h>   // strlen(), strncpy(), strtok()

#define NAME_LENGTH 64
#define LINE_LENGTH 1024
#define DELIMITER " \n"

/* The scores can be of any count */
typedef struct SCORES{
  int score;
  struct SCORES* prev;
  struct SCORES* next;
}SCORES;

/* the names can be of any count */
typedef struct RECORDS{
  char first_name[NAME_LENGTH +1];
  char last_name[NAME_LENGTH +1];
  SCORES* scores;
  struct RECORDS* prev;
  struct RECORDS* next;
}RECORDS;


int read_entries(FILE* fp, RECORDS* record, int verbose);
int free_me(RECORDS* record);

/* Run this sucker, instead of limiting the user to some uniq input.txt
 * file, we give them the selection to parse that to teh program, 
 * aswell as a request for a verbose output, where they can follow 
 * what is happening during teh run of it all.
 */

int main(int argc, char** argv)
{
  FILE* in_file;
  /* record will be the initial record, 
   * the first one at all time
   */
  RECORDS* record;
  /* cur_record will be pointing to the 
   * curent used record at all times
   */
  RECORDS* cur_record;
  /* scores will be pointing to the current
   * score assigned in the cur_record 
   */
  SCORES* scores;

  int count_records, count_scores, verbose = 0;
  
  /* we need to check if the program should be 
   * with verbose output or if it's just the file_name
   * thats been passed to it.
   */
  if(argc <= 1 || argc > 3)
    {
      printf("Usage: %s [-v] <filename>\n", argv[0]);
      return -1;
    }
  /* The arguments given are indeed "-v" "filename" */
  if(argv[1][0] == '-' && argc == 3)
    {
      verbose = 1;
      if(!(in_file = fopen(argv[2], "r")))
	{
	  printf("Unable to open file: %s\n", argv[2]);
	  return -1;
	}
    }
  /* it was just a filename that was given */
  else
    if(!(in_file = fopen(argv[1], "r")))
      {
	printf("Unable to open file: %s\n", argv[2]);
	return -1;
      }

  /* we allocate room for the very first read record */
  record = (RECORDS*) malloc(sizeof(RECORDS));
  record->prev = NULL;
  record->next = NULL;
  cur_record = record;
  if(read_entries(in_file, cur_record, verbose))
    {
      printf("Error reading entries from file.\n");
      free_me(record);
      return -1;
    }
  fclose(in_file);
  cur_record = record;
  count_records = 1;

  /* print what we've read */
  while(cur_record)
    {
      count_scores = 1;
      /* since it will allocate a NULL user, when theres an empty line
       * we will have to correct that 
       */
      if(strlen(cur_record->first_name) <=1)
	break;

      printf("Summary for user [%.3d]: %s, %s\n", count_records, cur_record->last_name, cur_record->first_name);
      scores = cur_record->scores;
      while(scores)
	{
	  /* since strtok() will give a NULL value, when dealing with EOL
	   * we will have to correct that
	   */
	  if(!scores->score)
	    break;

	  printf(" \t %d%c", scores->score, ((count_scores % 4) ? ' ' : '\n'));
	  scores = scores->next;
	  count_scores++;
	}
      printf("\n");
      count_records++;
      cur_record = cur_record->next;
    }

  free_me(record);
  return 0;
}

/* when reading everthing in the scores file, we need to dynamicaly 
 * allocate the memory needed from the heap.
 * since we're allocating one instance at a time, theres a slight 
 * overkill in the allocation, but since the fgets() will consume much
 * of the time spent here anyway, it's affordable.
 */

int read_entries(FILE* fp, RECORDS* record, int verbose)
{
  RECORDS* cur_record;
  RECORDS* next_record;
  SCORES* cur_score;
  SCORES* next_score;
  char *str, buffer[LINE_LENGTH +1];

  cur_record = (RECORDS*) malloc(sizeof(RECORDS));
  if(!cur_record)
    {
      printf("Error allocating space on the heap for cur_record\n");
      return 1;
    }
  cur_record->next = NULL;
  cur_record->prev = NULL;
  cur_record = record;
  while(fgets(buffer, LINE_LENGTH, fp))
    { /* buffer should contain "first_name last_name score1 ... scoreN\n" */
      /* any line should be longer than 2 chars */
      if(strlen(buffer) < 2)
	break;
      if(verbose)
	printf("Read line: %s\n", buffer); 
      /* first we strip the first_name and last_name */
      strncpy(cur_record->first_name, strtok(buffer, DELIMITER), NAME_LENGTH);
      if(verbose)
	printf("Stored into first_name: %s\n", cur_record->first_name);
      strncpy(cur_record->last_name, strtok(NULL, DELIMITER), NAME_LENGTH);
      if(verbose)
	printf("Stored into last_name: %s\n", cur_record->last_name );
 
      /* then run through the rest, collecting all scores */
      cur_score = (SCORES*) malloc(sizeof(SCORES));
      if(!cur_score)
	{
	  printf("Error allocating space on the heap for cur_score\n");
	  return 1;
	}
      cur_score->prev = NULL;
      cur_score->next = NULL;
      cur_record->scores = cur_score;
      while(NULL != (str = strtok(NULL, DELIMITER)))
	{
	  cur_score->score = atoi(str);
	  if(verbose)
	      printf("Stored into score: %d\n", cur_score->score); 
	  next_score = (SCORES*) malloc(sizeof(SCORES));
	  if(!next_score)
	    {
	      printf("Error allocating space on the heap for next_score\n");
	      return 1;
	    }
	  next_score->prev = cur_score;
	  cur_score->next = next_score;
	  cur_score = next_score;
	}
      next_record = (RECORDS*) malloc(sizeof(RECORDS));
      if(!next_record)
	{
	  printf("Error allocating space on the heap for next_record\n");
	  return 1;
	}
      next_record->prev = cur_record;
      cur_record->next = next_record;
      cur_record = next_record;
    }
  return 0;
}

/* when dealing with malloc, a nice thing to do, is to
 * free everything you've allocated, just to give back
 * to the system what you've proclaimed
 */

int free_me(RECORDS* record)
{
  RECORDS* cur_record;
  SCORES* cur_score;
  cur_record = record;

  /* now work your way to the last record
   * deleting everything that comes in your way 
   */

  while(cur_record)
    {
      cur_score = cur_record->scores;
      while(cur_score)
	{
	  if(!cur_score->next)
	    break;
	  cur_score = cur_score->next;
	  free(cur_score->prev);
	}
      if(!cur_record->next)
	break;
      cur_record = cur_record->next;
      free(cur_record->prev);
    }
  return 0;
}
Boy I'm glad I wrote the explanations to the functions while I was still sober... Now It would have been filled with some extraordinarily remark, that wouldn't make any sence what so ever...


Sorry, but I'm too drunk to highlight any of this code, as I would normaly do, in order to point out the key terms and restricted variables, such as int, void, stdout, stdin, etc.
__________________
Don't worry Ma'am, We're university students, We know what We're doing.
-----
If you pull the pin, Mr.Grenade would no longer be your friend.
-----
01000111 01101111 00100000 01000011 00100000 00100001

Last edited by redhead; 03-25-2005 at 12:34 AM. Reason: Found a small flaw in the free_me() function
redhead is offline   Reply With Quote
Old 03-24-2005, 10:43 PM   #7 (permalink)
JaySun
Registered User
 
Join Date: Mar 2005
Posts: 7
JaySun is on a distinguished road
Thanks, drunky! I will look it over and let you know if I have any questions.
JaySun is offline   Reply With Quote
Reply

Bookmarks

Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On


Similar Threads
Thread Thread Starter Forum Replies Last Post
combining arrays Engineer Standard C, C++ 11 03-12-2005 10:23 AM
2 questions about arrays and incudes files, and etc. slashdot Standard C, C++ 4 01-27-2005 08:39 AM
Do Multidimensional arrays work like a hash in Perl? philthee Java 1 10-22-2004 01:06 PM
Dynamic Arrays, the 'right' way. Mr.Anderson Standard C, C++ 10 10-05-2004 06:00 AM


All times are GMT -8. The time now is 04:06 PM.


Powered by vBulletin® Version 3.7.0
Copyright ©2000 - 2008, Jelsoft Enterprises Ltd.
Search Engine Optimization by vBSEO 3.0.0 RC8





Copyright © 2000-2008, Milano Interactive
Web Hosting provided by Portal 360 Web Hosting