Google Answers Logo
View Question
 
Q: Simple C programming question ( Answered 5 out of 5 stars,   2 Comments )
Question  
Subject: Simple C programming question
Category: Computers > Programming
Asked by: fikal-ga
List Price: $10.00
Posted: 17 Nov 2004 21:46 PST
Expires: 17 Dec 2004 21:46 PST
Question ID: 430506
To make this simplier for you guys, I made a small program based off
my much bigger program I am making.  I thought I knew pointers and
functions pretty well until now.  The program reads a file 'ryan.txt'
and is supposed to print out the  information.  For some reason I cant
get the array to work from function to function.  The file 'ryan.txt'
is as follows:

3
red 10
black 12
white 15



/* SMALL EXAMPLE OF BIGGER PROBLEM
	BY RYAN */


#include<stdio.h> /* input/output header */

void restore(char *a[][19], int *b[]);
void print(char *a[][19], int *b[]);

int main(void)
{
	
	/*int numbers, functions, characters, etc */
	char *item[100][19];
	int *quantity[100];
	int i;
	
	printf("1. To read chars.\n");
	printf("2. To print chars.\n");
	scanf("%d",&i);
	
	if (i == 1) 
		restore(item,quantity);
	else
		print(item,quantity);
    
	return 0;
}

void print(char *a[][19], int *b[]) {
	int j;
	for (j = 0;  j < 4;  j++) 
		printf( "%s  %d ", a[j], &b[j]);
	main();
}

void restore(char *a[][19], int *b[]) {
    int j,k;
	FILE * infile;
	infile = fopen( "ryan.txt","r" );
	fscanf( infile, "%d", &k); 
	for (j = 0;  j < k;  j++) 
		fscanf( infile, "%s %d ", a[j], &b[j]);
	printf("Array Created! YAY!\n");
	main();
}

Clarification of Question by fikal-ga on 18 Nov 2004 21:22 PST
the code you gave me did not work completely.  The message Array
Created! YAY! kepy on printing out until the program crashed.  I have
added a little to the program because if you notice the program reads
the number of lines that are going to be in the file first.  fscanf(
infile, "%d", &k);  I need the program to get the variable and by
using pointers allow the print function to use the &k variable.  I
will repost my program which now gives me errors with the pointers.  I
am sure someone here can fix this program and compile it w/ no flaws.
the variable k has been changed to number.  Thank you 

#include<stdio.h> /* input/output header */

int restore(char *a[][19], int *b[], int *number);
int print(char *a[][19], int *b[], int *number);

int main(void)
{
	
	/*int numbers, functions, characters, etc */
	char *item[100][19];
	int *quantity[100];
	int i;
    int *number=0;    
	
	printf("1. To read chars.\n");
	printf("2. To print chars.\n");
	while (1) {
	scanf("%d",&i);
	
        

	   if (i == 1) {
		   restore(item,quantity,number);
		   i=0; }
	   else
		    print(item,quantity,number);
			i=0;
         }
    
	return 0;
}

int print(char *a[][19], int *b[], int *number) {
	int j;
	for (j = 0;  j < *number;  j++) 
		printf( "%s  %d ", a[j], &b[j]);
	return *number;
}

int restore(char *a[][19], int *b[], int *number) {
    int j;
	FILE * infile;
	infile = fopen( "ryan.txt","r" );
	fscanf( infile, "%d", &number); 
	for (j = 0;  j < *number;  j++) 
		fscanf( infile, "%s %d ", a[j], &b[j]);
	printf("Array Created! YAY!\n");
	return *number;
}
Answer  
Subject: Re: Simple C programming question
Answered By: efn-ga on 18 Nov 2004 23:48 PST
Rated:5 out of 5 stars
 
Hi fikal,

You have some excess asterisks.  Let's start with the the quantity array.

int *quantity[100];

This declares quantity to be an array of 100 pointers to integers, but
you don't have 100 integers whose addresses you need to store.  What
you want here is just an array of integers, so you can store up to 100
integers.

int quantity[100];

Once we make this change, we have to adjust all the references to this
array accordingly.  So the b parameters to the restore and print
functions should be "int b[]" or "int* b" (these are equivalent), but
not "int *b[]".

In the restore function, fcanf expects a pointer to an integer.  b is
an array of integers now, so b[j] is an integer, so &b[j] is a pointer
to an integer, so the existing code is correct.

In the print function, printf expects an integer parameter to match
the "%d".  As we just saw, &b[j] is a pointer to an integer, not an
integer, so that expression does not work here.  The function should
just pass the integer value b[j] to printf, not the address of b[j].

Similar considerations apply to the item array.  You want an array of
100 19-character arrays, not an array of 100 arrays of 19 pointers to
characters.  You don't have 1900 characters for all these pointers to
address, and you need a place to store the character data.  So the
declaration should be:

char item[100][19];

As with the quantity array, we will need to change the function
parameters accordingly.  The a parameters should be declared "char
a[][19]".

In the print function, printf expects a pointer to characters to match
the %s format specification.  a[j] is actually an array of characters,
but it gets converted to a pointer to its first element when you pass
it as a parameter, so it will work with printf.

In the restore function, fscanf also expects a pointer to characters,
so a[j] also works there.

Similarly, the number variable in main should be an int, not a pointer
to int.  When main calls print and restore, it should pass the address
of this variable, &number.

The number parameter in restore is a pointer to an integer, and the
first fscanf call needs a pointer to an integer to match the "%d"
specification.  Therefore, the function should just pass number to
fscanf, not the address of number (&number) as it does now.

I think these are the main things to be fixed.

If you need more explanation of any of this advice or you find you
need more help to get the program working, please ask for a
clarification and I will advise you further.

Regards,

--efn

Request for Answer Clarification by fikal-ga on 19 Nov 2004 11:30 PST
that worked great, i have made one small additoin to my example
program that i can not figure out.  Theres something wrong with my add
function.  I seem to have trouble with double arrays.



#include<stdio.h> /* input/output header */

int restore(char a[][19], int b[], int *number);
int print(char a[][19], int b[], int *number);
int add(char a[][19], int b[], int howmuch, char product, int *number);
int main(void)
{
	
	/*int numbers, functions, characters, etc */
	char item[100][19],char product;
	int quantity[100];
	int i;
    int number=0,howmuch=0;    
	
	printf("1. To read chars.\n");
	printf("2. To print chars.\n");
	printf("3. To add chars.\n");
	while (1) {
	scanf("%d",&i);
	
        

	   if (i == 1) {
		   restore(item,quantity,&number);
		   i=0; }
	   if (i == 2) {
		    print(item,quantity,&number);
			i=0; }
	   if (i == 3) {
			scanf("%d%c",howmuch,product);
		    add(item,quantity, howmuch, product,&number);
			i=0; }
	   }
    
	return 0;
}

int print(char a[][19], int b[], int *number) {
	int j;
	for (j = 0;  j < *number;  j++) 
		printf( "%s  %d ", a[j], b[j]);
	return *number;
}

int restore(char a[][19], int b[], int *number) {
    int j;
	FILE * infile;
	infile = fopen( "ryan.txt","r" );
	fscanf( infile, "%d", number); 
	for (j = 0;  j < *number;  j++) 
		fscanf( infile, "%s %d ", a[j], &b[j]);
	printf("Array Created! YAY!\n");
	return *number;
}

int add(char a[][19], int b[], int howmuch, char product, int *number) {
	if (*number == 0)
		printf("Error: you must restore an order first\n");
	*number++;
	a[*number][19] = product;
	b[*number] = howmuch;
	return *number;
}

Clarification of Answer by efn-ga on 19 Nov 2004 18:40 PST
The scanf call in main needs work.  As in other cases, a "%d" in scanf
calls for a pointer to an integer.  howmuch is an integer, not a
pointer to an integer, so the main function should pass its address
(&howmuch), not its value.

I suspect you want product to be a character string, not a single
character.  If this is so, it should be declared as a character array.
 If it is, then passing its name to scanf will work, because the array
reference will be converted to a pointer to the array's first element.
 If you make this change, you should change the declaration of the
product parameter to the add function accordingly.  You should also
change the format specification passed to scanf from "%c" for a
character to "%s" for a string.

The add function assigns product to a[*number][19].  a[*number] is an
array of 19 characters and array subscripts start from zero, so the
elements of a[*number] are a[*number][0] through a[*number][18] and
a[*number][19] is beyond the bounds of the array.  Unfortunately, C
does not protect you from errors like this.

If you take my advice above and make product a string instead of a
character, assigning it to a[*number] will not work.  To copy a 
character string, you need to use a library function like strcpy or
strncpy.  strcpy is easier to use and strncpy is safer.

I hope this helps.

--efn

Request for Answer Clarification by fikal-ga on 20 Nov 2004 13:17 PST
here is the updated ver and im getting error C2440: '=' : cannot
convert from 'char [19]' to 'char'.  Thanks in advance, ur very
helpful!

#include<stdio.h> /* input/output header */
#include<string.h> /* some basic string command */

int restore(char a[][19], int b[], int *number);
int print(char a[][19], int b[], int *number);
int add(char a[][19], int b[], int howmuch, char product[], int *number);
int main(void)
{
	
	/*int numbers, functions, characters, etc */
	char item[100][19], product[19];
	int quantity[100];
	int i;
    int number=0,howmuch=0;    
	
	printf("1. To read chars.\n");
	printf("2. To print chars.\n");
	printf("3. To add chars.\n");
	while (1) {
	scanf("%d",&i);
	
        

	   if (i == 1) {
		   restore(item,quantity,&number);
		   i=0; }
	   if (i == 2) {
		    print(item,quantity,&number);
			i=0; }
	   if (i == 3) {
			scanf("%d%s",&howmuch,product);
		    add(item,quantity, howmuch, product,&number);
			i=0; }
	   }
    
	return 0;
}

int print(char a[][19], int b[], int *number) {
	int j;
	for (j = 0;  j < *number;  j++) 
		printf( "%s  %d ", a[j], b[j]);
	return *number;
}

int restore(char a[][19], int b[], int *number) {
    int j;
	FILE * infile;
	infile = fopen( "ryan.txt","r" );
	fscanf( infile, "%d", number); 
	for (j = 0;  j < *number;  j++) 
		fscanf( infile, "%s %d ", a[j], &b[j]);
	printf("Array Created! YAY!\n");
	return *number;
}

int add(char a[][19], int b[], int howmuch, char product[], int *number) {
	char tempproduct[19];
	int j=0;
	if (*number == 0)
		printf("Error: you must restore an order first\n");
	*number++;
	*number = j;
	strcpy(tempproduct,product);
	a[j][19] = tempproduct;
	b[j] = howmuch;
	return *number;
}

Clarification of Answer by efn-ga on 20 Nov 2004 18:13 PST
Hi Ryan,

*number = j;

This doesn't seem like a good idea.  Since j has previously been set
to zero, this means that the add function sets number to zero back in
main, and the add function always stores data in element 0.  Instead,
you can just use *number, as you had before.

strcpy(tempproduct,product);
a[j][19] = tempproduct;

While using strcpy is on the right track, this doesn't work, as the
compiler has told you.  You don't need tempproduct, and there is still
no element 19 in a 19-element array, only 0 through 18.  Instead, use
strcpy to copy from product directly to a[*number].

strcpy(a[*number], product);

--efn

Request for Answer Clarification by fikal-ga on 20 Nov 2004 21:03 PST
my add statement now looks like the following:

int add(char a[][19], int b[], int howmuch, char product[], int *number) {
	if (*number == 0)
		printf("Error: you must restore an order first\n");
	*number++;
	strcpy(a[*number], product);
	b[*number] = howmuch;
	return *number;
}

I get no errors but for some reason my print statement doesnt print
the new line and number still returns 3 instead of 4.  any
suggestions.  you are the best!

Clarification of Answer by efn-ga on 20 Nov 2004 22:43 PST
I missed this before.

1) *number++;

This could be parsed as 

2) (*number)++;

or 

3) *(number++);

Interpretation 2 increments the integer addressed by the number
pointer, which is what you want.  Interpretation 3 increments the
number pointer so it no longer points to the number variable in main,
then gets the integer the pointer addresses and does nothing with that
integer.

The rules of operator precedence determine which interpretation the
compiler uses.  As it happens, the ++ operator has higher precedence
than the * operator, so number clings to it rather than the *
operator, and the compiler uses the unwanted interpretation 3.

So you will have to add some parentheses to persuade the compiler to
use interpretation 2, to get the result you want.

--efn
fikal-ga rated this answer:5 out of 5 stars and gave an additional tip of: $2.00
very detailed explanation, i wish i could have your email address as a
future resouce to my c needs later on.  thank you again!

Ryan

Comments  
Subject: Re: Simple C programming question
From: padw-ga on 18 Nov 2004 05:52 PST
 
Hello,

I think there is just a small think to change.

Here is how your program works :
- Launch main()
- Do some operations...
- Call of print(char *a[][19], int *b[])...
     When you make this call the context of main is put on the memory stack
- Do print(...) every instruction is done
- If print(...) end with a return instruction all the context of main
is reloaded but you you make a new call of main() so the runtime put
the context of print(..) on the memory stack and then load main(and
exacute.


To correct your example I would suggest :


#include<stdio.h> /* input/output header */

void restore(char *a[][19], int *b[]);
void print(char *a[][19], int *b[]);

int main(void)
{
	
	/*int numbers, functions, characters, etc */
	char *item[100][19];
	int *quantity[100];
	int i;
        int goodwork = 1;
	
	printf("1. To read chars.\n");
	printf("2. To print chars.\n");
	scanf("%d",&i);
	
        while(goodwork == 1){

	   if (i == 1) 
		   goodwork = restore(item,quantity);
	   else
		   goodwork = print(item,quantity);
        }

    
	return 0;
}

void print(char *a[][19], int *b[]) {
	int j;
	for (j = 0;  j < 4;  j++) 
		printf( "%s  %d ", a[j], &b[j]);
	return 1;
}

void restore(char *a[][19], int *b[]) {
    int j,k;
	FILE * infile;
	infile = fopen( "ryan.txt","r" );
	fscanf( infile, "%d", &k); 
	for (j = 0;  j < k;  j++) 
		fscanf( infile, "%s %d ", a[j], &b[j]);
	printf("Array Created! YAY!\n");
	return 1;
}



The runtime will execute main(   ). When a call of print(...) append
the main context will be pull on the stack. The print(...) will be
execute then all the context of main will be restored and your array
item will be fill with the values of your files.

Sorry for my poor english, but I think this can help you.
Subject: Re: Simple C programming question
From: efn-ga on 19 Nov 2004 08:01 PST
 
Thanks for the rating and the tip.  Google Answers policies do not
allow me to post any contact information, but there are a number of
skilled programmers here who can help you if you would like to post
any more questions on this site.

Important Disclaimer: Answers and comments provided on Google Answers are general information, and are not intended to substitute for informed professional medical, psychiatric, psychological, tax, legal, investment, accounting, or other professional advice. Google does not endorse, and expressly disclaims liability for any product, manufacturer, distributor, service or service provider mentioned or any opinion expressed in answers or comments. Please read carefully the Google Answers Terms of Service.

If you feel that you have found inappropriate content, please let us know by emailing us at answers-support@google.com with the question ID listed above. Thank you.
Search Google Answers for
Google Answers  


Google Home - Answers FAQ - Terms of Service - Privacy Policy