Become a MacRumors Supporter for $50/year with no ads, ability to filter front page stories, and private forums.

larswik

macrumors 68000
Original poster
Sep 8, 2006
1,552
11
It says That I am getting a syntax error and I can't see what it is? I am deviating from the book with some tests to make sure I understand this before I move on. I am trying to pass a struct pointer as a parameter to my function .Then try to populate the char array 'words' in the struct with the char string 'Hello'.Then back in main I am trying to write the word out to the console. (I wrote out what I was trying to do so I could also see if my grammar was correct in stead of just saying I was getting a syntax error). The only thing I just thought of before I post this message is that I might need to populate the char with a for loop 1 letter at a time?

Header file
Code:
#define kMaxList 50
#define kMaxNumber 10

struct larsList 
{
	char words[kMaxList];
	char list[kMaxNumber];
};

main.c
Code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dvdTest.h"

void printStuff(struct larsList *myList);

int main (int argc, const char * argv[]) {
		
	struct larsList myList;
	
	printStuff(&myList);
	printf("The word is: %s", myList.words);

	
    return 0;
}
void printStuff(struct larsList *myList) 
{
	myList->words[kMaxList] = {'H','e','l','l','o','\0'};
}
 
You can only use that type of construct in an initializer when declaring the variable.

Try:

Code:
strcpy(mylist->words, "Hello");
 
Wow that was a fast reply :) I have not learned strcpy yet in the book. That would explain why It is not working if I can only do that when I declare the char array.

Thanks!
 
Instead of using the built-in function strcpy, you might want to write your own. Don't limit yourself only to for loops--experiment a little with while and do-while.
 
Oh, no strcpy() yet. Then write one. :)

Code:
char  *h = "Hello";  
char *d = myList->words;
while (*d++ = *h++);

Extra credit for explaining how this works.
 
haha... Ya that is a little above what I know so far, but you gave me an idea and this ended up working. I think I am going to miss the extra credit on that one :)

Code:
}
void printStuff(struct larsList *myList) 
{
	char theWord[6] = {'H','e','l','l','o','\0'};
	int i;
	
	for(i = 0; i <= 6; i++){
		myList->words[i] = theWord[i];
	}

}
 
Code:
#define kMaxList 50
#define kMaxNumber 10

struct larsList 
{
	char words[kMaxList];
	char list[kMaxNumber];
};

void printStuff(struct larsList *myList) 
{
	myList->words[kMaxList] = {'H','e','l','l','o','\0'};
}
Code:
void printStuff(struct larsList *myList)
{
  // you could do                                                                                       
  struct larsList stuff={{'H','e','l','l','o','\0'},{'\0'}};
 *myList=stuff;
 // but you can't do   myList->words = stuff.words;

 // you can do                                                                                        
 myList->words[0] = stuff.words[0];
 // but you can't do   myList->words[kMaxList] = stuff.words[kMaxList]; (Do you see why not?)                                                     
}
 
By the way,
One disadvantage of
Code:
struct larsList myStuff[1]={{{"Hello"},{"world"}}};
char *h = myStuff->words
char *d = myList->words;
while (*d++ = *h++);
compared to
Code:
char  *h = "Hello";  
char *d = myList->words;
while (*d++ = *h++);
is that
Code:
char  *h = "Hello";
doesn't waste as much space.

One advantage of
Code:
struct larsList myStuff={...}
is that
Code:
#define kMaxList 50
#define kMaxNumber 10

struct larsList
{
  char words[kMaxList];
  char list[kMaxNumber];
};
struct larsList myStuff={{"hello"},{"world without end"}};
char *h = myStuff.list;
char *d = myList->list;
while (*d++ = *h++);
generates a compile time error rather than run time error.
 
Code:
}
void printStuff(struct larsList *myList) 
{
	char theWord[6] = {'H','e','l','l','o','\0'};
	int i;
	
	for(i = 0; i <= 6; i++){
		myList->words[i] = theWord[i];
	}

}

Careful with the <=6 there. You are overrunning that array.
'H' == theWord[0];
'\0' == theWord[5];
theWord[6] == probably the first byte of int i;
 
That is the thing that screws me up sometimes. I count 'Hello' on my fingers and I come up with a 5 char array for that word. I then think I need the 6th char to be the zero terminator so 'char theWord[6]' to me works?

char theWord[6] is it '0-6' chars, or '0-5' chars?

So 'char theWord[6]' says I want 6 char variables but 'theWord[4]' means I am working with char number [4]?

-Lars
 
That is the thing that screws me up sometimes. I count 'Hello' on my fingers and I come up with a 5 char array for that word. I then think I need the 6th char to be the zero terminator so 'char theWord[6]' to me works?

char theWord[6] is it '0-6' chars, or '0-5' chars?

So 'char theWord[6]' says I want 6 char variables but 'theWord[4]' means I am working with char number [4]?

-Lars

When declaring an array, you give the number of elements you want available. When using an index into an array the valid values start at 0 and go to n-1 where n is the length of the array. So:
Code:
char theWord[6];
...
theWord[0] ='H';
theWord[1] ='e';
theWord[2] ='l';
theWord[3] ='l';
theWord[4] ='o';
theWord[5] ='\0';

theWord[6] would be past the end of the array, hence an overflow, meaning if you stored something there you would be overwriting something else inadvertently. This could cause no harm, or could cause your program to die a fiery death at some seemingly unrelated line.

-Lee
 
That is the thing that screws me up sometimes. I count 'Hello' on my fingers and I come up with a 5 char array for that word. I then think I need the 6th char to be the zero terminator so 'char theWord[6]' to me works?

When counting lengths of an array this works. When counting positions in an array, this doesn't work. For positions, the first count needs to be a closed fist which represents position zero, then the second count is the first finger or thumb, and so on.

char theWord[6] is it '0-6' chars, or '0-5' chars?

0-5 chars

So 'char theWord[6]' says I want 6 char variables but 'theWord[4]' means I am working with char number [4]?

Yes

This is one of the many reasons C is not taught as a first language by people who actually teach programming. Few other languages are as dangerous as to silently let you corrupt other memory by accessing an array past it's end. As a beginner, you can't be expected to be on the look out of these kinds of bugs. It's even hard for experienced C programmers to diagnose this kind of bug, who's symptom is a program crash far from the bug.

Beginners make mistakes. So they need a language that saves them from themselves. C is the complete opposite. C assumes you know what you're doing; which is why experienced programmers love it so much.

This is not discourage you at all Lars. It's just to point out that these mistakes are completely normal, and that part of the blame is on C. ;)
 
Thanks! I reread Jared post and understand my error with the '<=6'. I just took the [6] from theWord and used it for my counter not remembering that it only went to 5. For that to work I should have written it like this '<=5' or '<6'

Thank you.

-Lars
 
That is the thing that screws me up sometimes. I count 'Hello' on my fingers and I come up with a 5 char array for that word. I then think I need the 6th char to be the zero terminator so 'char theWord[6]' to me works?
One way to avoid having to count on your fingers is to let the compiler do it for you:
Code:
char theWord[] = {'H','e','l','l','o','\0'};
// which can also be written char theWord[] = {"Hello"};
	int i;	
	for(i = 0; i < (sizeof(theWord)/sizeof(theWorld[0])); i++){
		myList->words[i] = theWord[i];
	}
}
 
That is a nice tip, thanks DMI. This will help me to count when I run out of fingers :)

-Lars
 
That is a nice tip, thanks DMI. This will help me to count when I run out of fingers :)

-Lars

A few suggestions:
echo "my great string that is too long to eyeball its length" | wc
Edit: you still need to add 1 for the null terminator.

However, if you just need a fixed string you don't need an explicit array at all:
Code:
const char *myString = "This is my string";

-Lee
 
Last edited:
A beginner may be tempted to think being able to do
Code:
        char theWord[] = {"Hello"};
	for(i = 0; i < (sizeof(theWord)/sizeof(theWorld[0])); i++){
might mean that you could also do
Code:
        char *theWord = "Hello";
	for(i = 0; i < (sizeof(theWord)/sizeof(theWorld[0])); i++){
But the latter would not work, because sizeof(theWord) would be the size of the pointer, not the size of the array.
However, since "" strings are null terminated, you may not need a count, and can loop until the null:
Code:
	for(i = 0; theWord[i]; i++){
but if you are copying a string, you may need to be sure to write the loop such that the null is also copied, e.g.
Code:
	for(i = 0; myList->words[i] = theWord[i]; i++);
 
That brings up another question that I am a little unsure off, where to put the zero-terminator.

Example, lets say I create a 500 char array and only put the word hello in there.

theWord[500]= {"Hello"};
theWord[499] = '\0';

This will leave a lot of empty chars but still it has the Zero-terminator so it seems fine to me even though there is a lot of empty space. Now lets say later in the code I write this...

theWord[0] = {'W'};
theWord[1] = {'0'};
theWord[2] = {'r'};
theWord[3] = {'l'};
theWord[4] = {'d'};
theWord[5] = {'\0'};

It will replace the word 'Hello' and add a zero terminator to theWord[5] but also I have a zero terminator at theWord[499], is this OK or should I not zero terminate theWord[5] since theWord[499] already is already terminated for that char array?

-Lars
 
The zero-terminator should go after the last character in the string. This may or may not be the last character in the array.

The zero-terminator marks where in the array is the end of the string. All the positions in the array after the zero-terminator are not considered to be part of the string. If there happens to be multiple zero-terminators, then only the first one is significant.

So to further refine your C knowledge. A string is a sequence of characters followed immediately by a zero-terminator. A character array is not a string. A character array is just a sequence of characters. A character array can contain a string.

BTW You don't need to explicitly add a zero-terminator like you did in this code:

Code:
char theWord[500]= {"Hello"};
theWord[499] = '\0';

(I added the char, otherwise the code is outright wrong). Because a string literal automatically includes a zero-terminator. The code above is equivalent to the code below.

Code:
char theWord[500] = { 'H', 'e', 'l', 'l', 'o', '\0' };
theWord[499] = '\0';

Furthermore, the zero-terminator at position 499 is redundant/wrong because it's not immediately after the last character in the string.
 
I see. My worry was when the program is running if I said char theWord[500] it then blocks off a piece of memory for that array so the program can't accidentally write to that array block of memory and crash the program. I was unsure if I did not have a Zero Terminator at the end of the array, if the computer would see that as available memory if I had the zero terminator at theWord[5] = '\0'; instead of [499] to mark the end of that array.

But from what you said I guess once it initializes the char theWord[500] array the computer already knows not to write anything in to that array even if I set the zero terminator at theWord[5].

Thanks!

-Lars
 
But from what you said I guess once it initializes the char theWord[500] array the computer already knows not to write anything in to that array even if I set the zero terminator at theWord[5].

Yup, you're right. The char theWord[500] reserves enough memory to store 500 characters, and that memory won't be used for anything else. (Speaking loosely).
 
In my learning... I am trying to create a Header file for my struct and a Function Prototype for passing a struct as the parameter.

Then fill in a word at scanf to be placed in to the myArray[4].rating field. Using the Function I want to send myArray[5].rating as the parameter and have it duplicate myArray[4].rating to myArray[5].rating. Then back in Main print out the result. I am not getting an error message but warnings so I know I am close.

Header File
Code:
#define kRatingTotal 10
#define kComment 256

struct testArray {
	char rating[kRatingTotal];
	char comment[kComment];
};


void passArray(struct testArray myArray[4]);

Main.C
Code:
#include <stdio.h>
#include <string.h>
#include "struct_test.h"


int main (int argc, const char * argv[]) {
	
	struct testArray myArray[50];
	
	int theSize, theLen;
	
	printf("What is the rating:");
	scanf("%s", &myArray[4].rating);
	
	
	theSize = sizeof(myArray[4].rating);
	theLen = strlen(myArray[4].rating);
	
	
	printf("The Size is %d\n", theSize);
	printf("The len of the string is is %d\n", theLen);
	
	passArray(myArray[5].rating);
	
	printf("myArray 5 says: %s ", myArray[5].rating);
	
    return 0;
}
void passArray(struct testArray myArray[4]) {
	
	*myArray[5].rating = myArray[4].rating;
}
 
Code:
  passArray(myArray);
}

void passArray(struct testArray myArray[50]) {
  strcpy(myArray[5].rating,myArray[4].rating);
}
 
Code:
void passArray(struct testArray myArray[50]) {
   myArray[5] = myArray[4]; // also works, but it may not be advisable for a beginner to consider such things
}
 
Code:
  passArray(myArray);
}

void passArray(struct testArray myArray[50]) {
  strcpy(myArray[5].rating,myArray[4].rating);
}

This won't quite work. Because a copy of the array is passed into passArray, the changes within passArray won't be visible to main. You would need this:

Code:
    passArray(myArray);
    /* ... */
}

void passArray(struct testArray * myArray) {
    strcpy(myArray[5].rating, myArray[4].rating);
}
 
Register on MacRumors! This sidebar will go away, and you'll see fewer ads.