Thread: Passing Array of Strings to a function ??

  1. #1
    Registered User
    Join Date
    Dec 2008
    Posts
    12

    Passing Array of Strings to a function ??

    Ok I'm trying to make strings correspond to numbers but I having problems getting the information to and from the function convert (see code below). Can Anyone tell me what I'm doing wrong? I'm getting a warning about incompatable pointer type to do with the array I'm trying tp passing. Oh and is there any way I can tidy up 'convert', i can't seem to use strcmp with a switch?
    -----------------------------------------------------------------------------------------------------
    Code:
    #include<stdio.h>
    
    
    
    
    int convert(char name[40][40]);
    
    
    
    main()
    {
     char name[40][40];
     int array[12];	
    	
    	int i,x;
    	
    	for(i=1;i<=12;i++){
    	
    	printf("Please enter note %d in the series:",i);
    	scanf("%s",name[i]);
    	
    	
            
    
    	array[i]=convert(name[i]);
    
    
    
    	}
    	
    	
    	
    
    
    for(i=0;i<=11;i++) printf("%d\n\t",array[i]);
    	
    	
    
    }
    
    
    
    
    
    int convert(char name[40][40]){
    
    	
    int x,i=1;
    
    		
    
    		
    
    		for(i=1;i<=12;i++){
    
    		
    
    
    		if( strcmp(name[i],"C") == 0 || strcmp( name[i], "c")==0  ||strcmp( name[i], "B#" ) == 0 || strcmp( name[i], "bb")==0){
    		
    		x=0;
    		}
    		
    		else if( strcmp( name[i], "C#" ) == 0 || strcmp( name[i], "c#")==0||strcmp( name[i], "Db" ) == 0 || strcmp( name[i], "db")==0 ){
    		
    		x=1;
    		}
    		
    		else if( strcmp( name[i], "D" ) == 0 || strcmp( name[i], "d")==0){
    		
    		x=2;
    		}
    	
    		else if( strcmp( name[i], "D#" ) == 0 || strcmp( name[i], "d#")==0||strcmp( name[i], "Eb" ) == 0 || strcmp( name[i], "eb")==0 ){
    		
    		x=3;
    		}
     	
    		else if( strcmp( name[i], "E" ) == 0 || strcmp( name[i], "e")==0||strcmp( name[i], "Fb" ) == 0 || strcmp( name[i], "fb")==0 ){
    		
    		x=4;
    		}
    
    		else if( strcmp( name[i], "F" ) == 0 || strcmp( name[i], "f")==0||strcmp( name[i], "E#" ) == 0 || strcmp( name[i], "e#")==0 ){
    		
    		x=5;
    		}
    		
    		else if( strcmp( name[i], "F#" ) == 0 || strcmp( name[i], "f#")==0||strcmp( name[i], "Gb" ) == 0 || strcmp( name[i], "gb")==0 ){
    		
    		x=6;
    		}
    
    		else if( strcmp( name[i], "G" ) == 0 || strcmp( name[i], "g")==0 ){
    		
    		x=7;
    		}
    
    		else if( strcmp( name[i], "G#" ) == 0 || strcmp( name[i], "g#")==0||strcmp( name[i], "Ab" ) == 0 || strcmp( name[i], "ab")==0 ){
    		
    		x=8;
    		}
    
    		else if( strcmp( name[i], "A" ) == 0 || strcmp( name[i], "a")==0 ){
    		
    		x=9;
    		}
    
    		else if( strcmp( name[i], "A#" ) == 0 || strcmp( name[i], "a#")==0||strcmp( name[i], "Bb" ) == 0 || strcmp( name[i], "bb")==0 ){
    		
    		x=10;
    		}
    
    		else if( strcmp( name[i], "B" ) == 0 || strcmp( name[i], "b")==0||strcmp( name[i], "Cb" ) == 0 || strcmp( name[i], "cb")==0 ){
    		
    		x=11;
    		}
    		
    		else {
    		printf("Not a Vaild Entry!!!\n");
    		printf("Please enter note %d in the series AGAIN:",i);
    		scanf("%s",name[i]);
    		convert(name[i]);
    
    		}
    }
    
    return x;
    
    }
    -----------------------------------------------------------------------------------------------------

    Any help would be greatly appreciated

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    28,413
    Kindly indent your code more consistently and post the exact error message.
    Quote Originally Posted by Bjarne Stroustrup (2000-10-14)
    I get maybe two dozen requests for help with some sort of programming or design problem every day. Most have more sense than to send me hundreds of lines of code. If they do, I ask them to find the smallest example that exhibits the problem and send me that. Mostly, they then find the error themselves. "Finding the smallest program that demonstrates the error" is a powerful debugging tool.
    Look up a C++ Reference and learn How To Ask Questions The Smart Way

  3. #3
    Registered User
    Join Date
    Dec 2008
    Posts
    12
    Ok just realised a big mistake I don't need the for loop in convert or the variable 'i' as I am just passing the string to it each time it is typed in. The code now looks like:

    Code:
    #include<stdio.h>
    
    
    
    
    int convert(char name[40][40]);
    
    
    
    main(){
    
     	char name[40][40];
    	static int array[11];	
    	
    	int i;
    	
    	for(i=0;i<=11;i++){
    	
    		printf("Please enter note &#37;d in the series:",i+1);
    		scanf("%s",name[i]);
    		array[i]=convert(name[i]);
    	}
    	
    
    
    	printf("\n\t");
    	
    	for(i=0;i<=11;i++){
    
    		printf("%d\n\t",array[i]);
    	}
    	
    
    }
    
    
    
    
    
    int convert(char name[40][40]){
    
    	
    	int x;
    
    		
    
    		if( strcmp(name,"C") == 0 || strcmp( name, "c")==0  ||strcmp( name, "B#" ) == 0 || strcmp( name, "b#")==0){
    		
    		x=0;
    		}
    		
    		else if( strcmp( name, "C#" ) == 0 || strcmp( name, "c#")==0||strcmp( name, "Db" ) == 0 || strcmp( name, "db")==0 ){
    		
    		x=1;
    		}
    		
    		else if( strcmp( name, "D" ) == 0 || strcmp( name, "d")==0){
    		
    		x=2;
    		}
    	
    		else if( strcmp( name, "D#" ) == 0 || strcmp( name, "d#")==0||strcmp( name, "Eb" ) == 0 || strcmp( name, "eb")==0 ){
    		
    		x=3;
    		}
     	
    		else if( strcmp( name, "E" ) == 0 || strcmp( name, "e")==0||strcmp( name, "Fb" ) == 0 || strcmp( name, "fb")==0 ){
    		
    		x=4;
    		}
    
    		else if( strcmp( name, "F" ) == 0 || strcmp( name, "f")==0||strcmp( name, "E#" ) == 0 || strcmp( name, "e#")==0 ){
    		
    		x=5;
    		}
    		
    		else if( strcmp( name, "F#" ) == 0 || strcmp( name, "f#")==0||strcmp( name, "Gb" ) == 0 || strcmp( name, "gb")==0 ){
    		
    		x=6;
    		}
    
    		else if( strcmp( name, "G" ) == 0 || strcmp( name, "g")==0 ){
    		
    		x=7;
    		}
    
    		else if( strcmp( name, "G#" ) == 0 || strcmp( name, "g#")==0||strcmp( name, "Ab" ) == 0 || strcmp( name, "ab")==0 ){
    		
    		x=8;
    		}
    
    		else if( strcmp( name, "A" ) == 0 || strcmp( name, "a")==0 ){
    		
    		x=9;
    		}
    
    		else if( strcmp( name, "A#" ) == 0 || strcmp( name, "a#")==0||strcmp( name, "Bb" ) == 0 || strcmp( name, "bb")==0 ){
    		
    		x=10;
    		}
    
    		else if( strcmp( name, "B" ) == 0 || strcmp( name, "b")==0||strcmp( name, "Cb" ) == 0 || strcmp( name, "cb")==0 ){
    		
    		x=11;
    		}
    		
    		else {
    		printf("Not a Vaild Entry!!!\n");
    		printf("Please enter note in the series AGAIN:");
    		scanf("%s",name);
    		convert(name);		
    
    		}
    
    return x;
    
    }
    But there is a problem in the last else it does not return the correct value to main. I keep getting -1 ? The exact error is:

    Warning passing arg 1 from 'strcmp' from incompatible pointer type

    Of course there is one of these for each strcmp used.

  4. #4
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    For whatever reason (and someone please correct me if I'm wrong!), in C you can only allow pass and modify a char list (2D array) if it is malloced onto the heap like this:
    Code:
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    int testfunc (char **list) {
    	strcpy(list[1],"!!");
    	return 0;
    }
    
    int main () {
    	int i;
    	char *list[3];
    	for (i=0;i<3;i++) {
    		list[i]=malloc(3);
    		sprintf(list[i],"#&#37;d",i+1);
    	}
    	testfunc(list);
    	for (i=0;i<3;i++) {
    		printf("%s\n",list[i]);
    		free(list[i]);
    	}
    	return 0;
    }
    Output:
    Code:
    #1
    !!
    #3
    In other words you cannot pass char list[40][40] and expect your function to change "list" in main(). You cannot even use a pointer to list to do this. "list" must be heap allocated. This is the only way (unless someone has a better one).

    I've heard this isn't an issue in C++, and I'm certain the phenomenon is very, very poorly explained in virtually all of the C documentation I've seen, and discussions of it usually seem to get bogged down in what "pass by reference" means.

    A more normative method is to return a pointer, and if you need an int to pass that by ref:
    Code:
    char **testfunc (char list[3][3], int *retv)
    Last edited by MK27; 12-07-2008 at 10:21 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  5. #5
    Registered User
    Join Date
    Dec 2007
    Posts
    2,675
    You're going to overrun your array bounds here, and crash:
    Code:
    static int array[11];	
    int i;
    for(i=0;i<=11;i++){
    Should be:
    Code:
    static int array[12];	
    int i;
    for(i=0;i<12;i++){
    Your convert function is wrong, obviously. Its prototype should be something like:
    Code:
    int convert(const char *note)
    {
        int i = 0;
        if (strcmp(note, "C") == 0 ||
            strcmp(note, "B#") == 0 ||
            strcmp(note, "c") == 0 ||
            strcmp(note, "b#") == 0)
        {
            return 0;
        }
    
        if (strcmp(note, "Db") == 0 ||
            strcmp(note, "C#") == 0 ||
            strcmp(note, "db") == 0 ||
            strcmp(note, "c#") == 0)
        {
            return 1;
        }
    }

  6. #6
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    I just noticed you call "convert" in main's for loop, and indeed the function itself isn't processing an array of strings, it's a single string! So rags_to_riches has a more appropriate solution. You do not really need to "pass an array of strings".

    Still, if anyone can confirm or deny about what I wrote re: heap allocating arrays of strings for functions, it would be much appreciated
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  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
    > Still, if anyone can confirm or deny about what I wrote re: heap allocating arrays of strings for functions, it would be much appreciated
    You're just wrong, that's all.
    Arrays, no matter how many dimensions, and no matter how you dress up the declaration, are always passed by reference.


    Aside from the long-winded code, the OP only needed
    array[i]=convert(name);
    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
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Salem View Post
    You're just wrong, that's all.
    How? In the sense that there is another method of passing and modifying an array without using the return value? Show me.
    Arrays, no matter how many dimensions, and no matter how you dress up the declaration, are always passed by reference.
    I'm not denying that. It seems to me the issue is where the reference is to.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  9. #9
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    The *ONLY* passing method to a function in C, is by *copying*. There is NO "passing by reference".

    We get our "passing by reference" *in effect*, by copying pointers addresses. That is, since the pointer address is the same as the copy of the pointer address, we act like it's passing the original.

    There is no difference between changing a malloc'd array, and changing an array on the stack. You didn't get the array to change because you copied the whole array in that function.

    I'm not going to give you code to confirm this, because I don't believe in it - I believe you learn best by discovering it yourself - with guidance.

  10. #10
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Adak View Post
    There is no difference between changing a malloc'd array, and changing an array on the stack. You didn't get the array to change because you copied the whole array in that function.

    I'm not going to give you code to confirm this, because I don't believe in it - I believe you learn best by discovering it yourself - with guidance.
    You are not going to give me code that won't work, is what you mean. You cannot pass a (2D) stack char array to a function, modify it, and have the changes take place back in main, unless you return a new pointer.

    ps. If by "you", you mean me, I did change the array and you should read more carefully....so there
    Last edited by MK27; 12-07-2008 at 11:30 AM.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  11. #11
    Registered User
    Join Date
    Sep 2006
    Posts
    8,868
    Quote Originally Posted by MK27 View Post
    You are not going to give me code that won't work, is what you mean. ]You cannot pass a stack char array to a function, modify it, and have the changes take place back in main, unless you return a new pointer.

    ps. If by "you", you mean me, I did change the array and you should read more carefully....so there
    Good - get angry! I guess it helps you in the discovery process.

    A char array is the same as an integer array! In one case the words are 8 bits, and in the other case, the words are 16 or 32 bits. They're both just strings of binary words to the computer.

    I pass stack char array's all the time. Fact is, I don't malloc all that much. I'm not sure I know what you mean by "and have the changes take place back in main".

    The changes take place in RAM, or some other physical device. Main has nothing to do with that.
    Last edited by Adak; 12-07-2008 at 11:34 AM.

  12. #12
    and the hat of int overfl Salem's Avatar
    Join Date
    Aug 2001
    Location
    The edge of the known universe
    Posts
    39,659
    Consider
    Code:
    void foo ( char a[10][20] ) {
        strcpy( a[0], "hey, it works" );
        a[1][0] = '!';
    }
    void bar ( char a[][20] ) {
        strcpy( a[0], "hey, it works" );
        a[1][0] = '!';
    }
    void baz ( char (*a)[20] ) {
        strcpy( a[0], "hey, it works" );
        a[1][0] = '!';
    }
    
    int main ( ) {
        char arr[10][20];
        foo( arr );
        bar( arr );
        baz( arr );
        return 0;
    }
    Anything you can do in main() with the array, you can also do in the function as well. So if the array is modifyable in main (not declared const), then you can modify it in the function as well.

    Note that foo(), bar() and baz() are functionally identical, despite the different declarations of the parameter. They all mean the same thing to the compiler. The lack of any "*" in the first two does NOT mean you're getting a copy of the array all of a sudden.

    The only things which would be different would be:
    - you can INITIALISE the array in main, but you can't reinitialise the array inside the function.
    - sizeof(arr) in main gives a different answer to sizeof(a) in the function.



    My guess is you tried this once with a
    char *msg = "hello";
    kinda thing once, and then tried to modify your string literal in a function, and got a segfault for your trouble.

    Only you didn't understand the real reason for the problem, and so decided it was a problem with the parameter passing mechanism instead.
    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.

  13. #13
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300
    Quote Originally Posted by Adak View Post
    I pass stack char array's all the time. Fact is, I don't malloc all that much. I'm not sure I know what you mean by "and have the changes take place back in main".
    I pass stack char arrays all the time. My point is there is some significant syntax difference, in C, between a char array and a char 2D array. If you don't know what I meant by "having the changes take place in main", then obviously you don't use the arrays in this manner altho you may pass them all the time. This is the difference between:

    Code:
    void func (char **string);
    //to call:
    char *string;
    func(&string);
    and
    Code:
    void func (char *string);
    //to call:
    void func(string);
    Do you understand what I mean by "having the changes take place in main" (or wherever func is called from) now? In the first case, whatever happens to *string in func will apply back in main() after func is called. In the second case, whatever happened to string in func WILL NOT apply back in main() after func is called.

    Now, try and apply this logic to a 2D "list" (char list[40][40]) and you will find out what I mean by syntax differences, because the corallary to the first case is what was in my initial post.

    The changes take place in RAM, or some other physical device. Main has nothing to do with that.
    You're a kook. So about the heap...
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  14. #14
    spurious conceit MK27's Avatar
    Join Date
    Jul 2008
    Location
    segmentation fault
    Posts
    8,300

    Cool

    Okay I'm wrong.
    C programming resources:
    GNU C Function and Macro Index -- glibc reference manual
    The C Book -- nice online learner guide
    Current ISO draft standard
    CCAN -- new CPAN like open source library repository
    3 (different) GNU debugger tutorials: #1 -- #2 -- #3
    cpwiki -- our wiki on sourceforge

  15. #15
    C++まいる!Cをこわせ!
    Join Date
    Oct 2007
    Location
    Inside my computer
    Posts
    24,654
    And since none has been kind enough to post some indented code, I'll show you how it's done.
    Code:
    #include <stdio.h>
    
    int convert(char name[40][40]);
    
    int main()
    {
    	char name[40][40];
    	static int array[11];	
    	int i;
    	for (i = 0; i <= 11; i++)
    	{
    		printf("Please enter note &#37;d in the series:",i+1);
    		//scanf("%s",name[i]);
    		array[i] = convert(name[i]);
    	}
    	printf("\n\t");
    	for (i = 0; i<= 11; i++)
    	{
    		printf("%d\n\t", array[i]);
    	}
    }
    
    int convert(char name[40][40])
    {
    	int x;
    	if ( strcmp(name, "C") == 0 || strcmp(name, "c") == 0 || strcmp(name, "B#") == 0 || strcmp(name, "b#" ) == 0)
    		x = 0;
    	else if( strcmp( name, "C#" ) == 0 || strcmp( name, "c#")==0||strcmp( name, "Db" ) == 0 || strcmp( name, "db")==0 )
    		x=1;
    	else if( strcmp( name, "D" ) == 0 || strcmp( name, "d")==0)
    		x=2;
    	else if( strcmp( name, "D#" ) == 0 || strcmp( name, "d#")==0||strcmp( name, "Eb" ) == 0 || strcmp( name, "eb")==0 )
    		x=3;
    	else if( strcmp( name, "E" ) == 0 || strcmp( name, "e")==0||strcmp( name, "Fb" ) == 0 || strcmp( name, "fb")==0 )
    		x=4;
    	else if( strcmp( name, "F" ) == 0 || strcmp( name, "f")==0||strcmp( name, "E#" ) == 0 || strcmp( name, "e#")==0 )
    		x=5;
    	else if( strcmp( name, "F#" ) == 0 || strcmp( name, "f#")==0||strcmp( name, "Gb" ) == 0 || strcmp( name, "gb")==0 )
    		x=6;
    	else if( strcmp( name, "G" ) == 0 || strcmp( name, "g")==0 )
    		x=7;
    	else if( strcmp( name, "G#" ) == 0 || strcmp( name, "g#")==0||strcmp( name, "Ab" ) == 0 || strcmp( name, "ab")==0 )
    		x=8;
    	else if( strcmp( name, "A" ) == 0 || strcmp( name, "a")==0 )
    		x=9;
    	else if( strcmp( name, "A#" ) == 0 || strcmp( name, "a#")==0||strcmp( name, "Bb" ) == 0 || strcmp( name, "bb")==0 )
    		x=10;
    	else if( strcmp( name, "B" ) == 0 || strcmp( name, "b")==0||strcmp( name, "Cb" ) == 0 || strcmp( name, "cb")==0 )
    		x=11;
    	else 
    	{
    		printf("Not a Vaild Entry!!!\n");
    		printf("Please enter note in the series AGAIN:");
    		//scanf("%s",name);
    		convert(name);		
    	}
    	return x;
    }
    Also took the liberty to remove the lot of unnecessary lines.
    And then I'll hand out the usual helpful links.
    Do not use scanf to read strings, or use it properly: https://apps.sourceforge.net/mediawi...tle=Scanf_woes
    Do not use implicit main: http://cpwiki.sourceforge.net/Implicit_main
    Last edited by Elysia; 12-07-2008 at 12:56 PM.
    Quote Originally Posted by Adak View Post
    io.h certainly IS included in some modern compilers. It is no longer part of the standard for C, but it is nevertheless, included in the very latest Pelles C versions.
    Quote Originally Posted by Salem View Post
    You mean it's included as a crutch to help ancient programmers limp along without them having to relearn too much.

    Outside of your DOS world, your header file is meaningless.

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. function passing argument..array ?
    By jochen in forum C Programming
    Replies: 2
    Last Post: 09-30-2007, 11:53 AM
  2. Replies: 28
    Last Post: 07-16-2006, 11:35 PM
  3. Dikumud
    By maxorator in forum C++ Programming
    Replies: 1
    Last Post: 10-01-2005, 06:39 AM
  4. Problem with Visual C++ Object-Oriented Programming Book.
    By GameGenie in forum C++ Programming
    Replies: 9
    Last Post: 08-29-2005, 11:21 PM
  5. passing array of structures to function
    By bvnorth in forum C Programming
    Replies: 3
    Last Post: 08-22-2003, 07:15 AM