Thread: exercise program argv pointer arrays

  1. #1
    Registered User Fauveboy's Avatar
    Join Date
    Apr 2014
    Posts
    42

    exercise program argv pointer arrays

    I've attached the programme iscale.c which is taken from an exercise in the audio programming book.

    I get confused by aprox line 50 where it says:

    notes = atoi(argv[1]);

    as far as I can tell argv[1] is holding the char for a flag argument? which looks like to me that is even ensured to be tested in the while before. Then all of a sudden argv[1] is a value !? It doesn't make sense. I would have thought that argv looks like so, does it not:

    argv[0] = ./iscale
    argv[1] = [-m] or [-i]
    argv[2] = value

    this also means Im not sure what: notes = atoi(argv[1]) is doing?

    it looks like this statments saying let me take -m or -i and make it an integer?

    Can someone correct my thinking please,

    Many thanks!

    Code:
    /* iscale.c */
    /* generate E.T tables for N-notes to the octave (N <= 24) */
    #include <stdio.h>
    #include <stdlib.h>
    #include <math.h>
    
    
    /* usage iscale [-m] [-i] N startval [outfile.txt]
    	-m : sets format of startval as MIDI note
    	-i : prints the calculated interval as well as the abs freq
    	outfile: optional text filename for output data
    */
    
    
    int main(int argc, char* argv[])
    {
    	int notes,i;
    	int ismidi = 0;
    	int write_interval = 0;
    	int err = 0;
    	double startval,basefreq,ratio;
    	FILE* fp;
    	double intervals[25];
    
    
    	/* check first arg for flag option: argc at least 2 */
    	while(argc > 1){
    		if(argv[1][0]=='-'){
    			if(argv[1][1]== 'm')
    				ismidi = 1;
    				else if(argv[1][1]== 'i')
    					write_interval = 1;
    				else {
    					printf("error: inrecognized option %s\n",argv[1]);
    					return 1;
    				}
    				/* step up to next arg  */
    				argc--;
    				argv++;
    		}
    	else
    		break;
    	}
    
    
    	if(argc < 3){
    		printf("insufficient arguments\n");
    		printf("Usage: iscale [-m][-i] N startval [outfile.txt]\n");
    		return 1;
    	}
    /* now read and check all arguments */
    /* we now expect argv[1] to hold N and argv[2] starval */
    // shuld argv[1] not be argv[2] here?
    	notes = atoi(argv[1]);
    	if(notes < 1 || notes > 24){
    	printf("error: N out of range. Must be between 1 and 24.\n");
    	return 1;
    	}
    	startval = atof(argv[2]);
    	if(ismidi){
    		if(startval > 127.0){
    		printf("error: MIDI startval must be <= 127.\n");
    		return 1;
    		}
    	/* for MIDI, startval = 0 is legal */
    		if(startval < 0.0){
    		printf("error: MIDI startval must be >= 127.\n");
    		return 1;
    		}
    	}
    	else { /* it's freq: must be positive number */
    	/* check low limit */
    		if(startval <= 0.0){
    		printf("error: frequency starval must be positive.\n");
    		return 1;
    		}
    	}
    
    
    	/* check for optional filename */
    	fp = NULL;
    	if(argc==4){
    		fp = fopen(argv[3],"w");
    		if(fp==NULL){
    		printf("WARNING: unable to create file %s\n", argv[3]);
    		perror("");
    		}
    	}
    
    
    /* all params ready - fill array and write to file if created */
    		/* find basefreq, if val is MIDI */
    	if(ismidi){
    		double c0,c5;
    		/* find base MIDI note */
    		ratio = pow(2.0,1.0 / 12.0);
    		c5 = 220.0 * pow(ratio,3);
    		c0 = c5 * pow(0.5,5);
    		basefreq = c0 * pow(ratio,startval);
    	}
    	else
    		basefreq = startval;
    
    
    	/* calc ratio from notes, and fill the array */
    	ratio = pow(2.0,1.0/notes);
    	for(i=0;i <= notes; i++){
    		intervals[i] = basefreq;
    		basefreq *= ratio;
    	}
    
    
    /* finally, read array, write to screen, and optionally to file */
    
    
    	for(i=0; i <= notes; i++){	
    		if(write_interval)
    		printf("%d:\t%f\t%f\n", i, pow(ratio,i), intervals[i]);
    		else
    		printf("%d:\t%f\n", i, intervals[i]);
    		if(fp){
    			if(write_interval)
    				err = fprintf(fp,"%d:\t%f\t%f\n",
    					i, pow(ratio,i), intervals[i]); 
    			else 
    				err = fprintf(fp,"%d:\t%f\n", i, intervals[i]);
    			if(err < 0)
    				break;
    		}
    	}
    	
    	if(err < 0)
    		perror("There was an error writing the file. \n");
    	if(fp)
    		fclose(fp);
    	return 0;
    }
    Attached Files Attached Files
    Last edited by Fauveboy; 10-23-2018 at 02:17 AM.

  2. #2
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,159
    Quote Originally Posted by Fauveboy
    as far as I can tell argv[1] is holding the char for a flag argument? which looks like to me that is even ensured to be tested in the while before. Then all of a sudden argv[1] is a value !? It doesn't make sense. I would have thought that argv looks like so, does it not:
    You are right about that at the start of the main function, but read more carefully the block of code marked by the "check first arg for flag option: argc at least 2". In particular, notice the argv++. When you increment the pointer argv, the previous argv[2] becomes the new argv[1]. The reason for doing this is that the option is after all optional, so if it isn't an option, argv is not incremented.
    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
    and the Hat of Guessing tabstop's Avatar
    Join Date
    Nov 2007
    Posts
    14,336
    As another note, there's no reason (based just on the code/usage message inside the code) that you can't have both -m and -i options (that optional flag checker is a loop, after all). In that case, you'll end up knocking two off of argc (and moving argv forward twice) to get the command line to a stable position.

  4. #4
    Registered User Fauveboy's Avatar
    Join Date
    Apr 2014
    Posts
    42
    thank you for your answer. I'm not sure it has clicked yet

    if argv[1] is checked in the loop then the statment argv++ occurs I only see how we're now on argv[2]. which is confusing currently because the if statment expliciyly checks argv[1].

    surely in this loop
    - argv[1] gets checked
    - argv++
    - argv[2] << what we're now on
    - argv[1] checked again

    this isnt the case?

  5. #5
    C++ Witch laserlight's Avatar
    Join Date
    Oct 2003
    Location
    Singapore
    Posts
    27,159
    Quote Originally Posted by Fauveboy
    if argv[1] is checked in the loop then the statment argv++ occurs I only see how we're now on argv[2]. which is confusing currently because the if statment expliciyly checks argv[1].
    Perhaps an example would be instructive:
    Code:
    #include <stdio.h>
    
    int main(void)
    {
        const char *source[] = {"a", "sample", "list", "of", "words"};
        const char **words = source;
        int i;
        for (i = 0; i < 4; ++i)
        {
            printf("The word at index %d is: %s\n", i, words[i]);
        }
        words++;
        printf("After incrementing words...\n");
        for (i = 0; i < 4; ++i)
        {
            printf("The word at index %d is: %s\n", i, words[i]);
        }
        return 0;
    }
    Quote Originally Posted by Fauveboy
    surely in this loop
    - argv[1] gets checked
    - argv++
    - argv[2] << what we're now on
    - argv[1] checked again

    this isnt the case?
    That isn't the case. argv++ means that argv now points to argv[1], i.e., the new argv[0] is the original argv[1]. Therefore, checking argv[1] actually checks the original argv[2].
    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

Popular pages Recent additions subscribe to a feed

Similar Threads

  1. Exercise - pointer
    By khelkely in forum C Programming
    Replies: 1
    Last Post: 10-17-2013, 08:35 PM
  2. help with arrays and argv in ANSI C program
    By noobneedhelp in forum C Programming
    Replies: 1
    Last Post: 03-05-2013, 10:55 PM
  3. Array of pointers and pointer for arrays with argv
    By thames in forum C Programming
    Replies: 4
    Last Post: 12-02-2012, 10:24 AM
  4. matrix- exercise the use of arrays in the code.
    By CproG100 in forum C Programming
    Replies: 31
    Last Post: 08-28-2012, 07:40 AM
  5. exercise with pointer and structs
    By xphoenix in forum C Programming
    Replies: 4
    Last Post: 06-29-2010, 09:46 AM

Tags for this Thread