Link to home
Start Free TrialLog in
Avatar of Scott Fell
Scott FellFlag for United States of America

asked on

C code to pass string data from argv to another function.

On the code below my goal is to take three pieces of data that gets passed via the command like like "test.exe c 18 something" in the main() and pass the data to function called function() where I can verify the data meets some requirements.  The two printf() functions work in the main().  However, when I try and pass a string (argv[3]/prefix), I can't seem to get the full string parsed out from the third variable (prefix).  Code is below.

#include <malloc.h>
#include <string.h>
#include <stdio.h>

char location = 'r';
char *prefix = NULL;
int prefix_length = 0;
char *format = NULL;
int font_size = 0;

int function(location, font_size, prefix)
{
    printf("prefix=%c\n", location);    
    printf("prefix=%d\n", font_size);   
    printf("prefix=%s\n", prefix);      
    return 0;
}


int main(int argc, char **argv)
{ 
    printf("In main: x = %s y = %s z=%s\n", argv[1], argv[2],argv[3]); // works as expected 
	
	char location = *argv[1];
    int  font_size = atoi(argv[2]);
    
    //prefix = (char *)malloc(256);
    
    printf("prefix=%s\n",argv[3]); // prefix matchs argv[3]
	
	function(location,font_size,argv[3]); // pass data to function
	
    return 0; 
} 

Open in new window


Below will throw, "warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'int'"
printf("prefix=%s\n", prefix);    

Open in new window

If I change to
printf("prefix=%c\n", prefix);    

Open in new window

will get the first character.

My end goals are to be able to something like
prefix_length = strlen(prefix);
        if (prefix_length < 0 || prefix_length > 40) {
                printf("error: 0 <= prefix length <= 40\n");
                return 1;
        }

Open in new window


or
if(prefix == 'xxxyyy')
{
    return 1;
}
else
{
   return 0;
}

Open in new window


The original code that goes with with this added in the function() that tested.
 prefix = (char *)malloc(256);

Open in new window


I
ASKER CERTIFIED SOLUTION
Avatar of Kent Olsen
Kent Olsen
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of phoffric
phoffric

I am curious to know what compiler and platform you use that does not give compilation error for line 11
int function(location, font_size, prefix)
Is this C99?
Avatar of Scott Fell

ASKER

Microsoft (R) C/C++ Optimizing Compiler Version 19.20.27508.1 for x86
This seems to be working
#include <malloc.h>
#include <string.h>
#include <stdio.h>

char location = 'r';
char *prefix = NULL;
int prefix_length = 0;
char *format = NULL;
int font_size = 0;

int function(char* location,int font_size, char* prefix)
{
    printf("prefix=%s\n", location);    
    printf("prefix=%d\n", font_size);   
    printf("prefix=%s\n", prefix);      
    return 0;
}


int main(int argc, char **argv)
{ 
    printf("In main: x = %s y = %s z=%s\n", argv[1], argv[2],argv[3]); // works as expected 
	
    char *location = argv[1];
    int  font_size = atoi(argv[2]);
    
    //prefix = (char *)malloc(256);
    char *prefix = argv[3];
   
	
	function(location,font_size,prefix); // pass data to function
	
    return 0; 
} 

Open in new window


What does memory allocation add here with,
prefix = (char *)malloc(256);

Open in new window

In this case, a prefix could be NULL or it may contain probably less than 20 or 30 characters, more likely 3 or 4.
main() is a bit different w.r.t. prefix between the OP and your recent post. In OP,  the prefix is allocating memory presumably to fill it in later (per your comment). In last post, line 27 prefix refers to the global prefix, and line 28 prefix is a different local variable unrelated (at the moment) to the global variable. So,at the moment, line 27 is not adding anything of significance.
It is very confusing having a local and a global prefix in the same function.
Thank you Paul.

This is the original code I am working from. In this code, the prompt() function is prompting the user for some variables. My end goal is to pass those same variables through the command line instead.  I changed the name of the prompt() function to my test case above. My plan is to use that function for data verification.  Then keep everything else the same.

Honestly, a first I thought this would be easier. There is more to think about with C than I realized.

/*
Copyright 2013 Gregory Hildstrom

This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.

This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
GNU General Public License for more details.

You should have received a copy of the GNU General Public License
along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

/*
This program generates a labeling pdf to be overlayed on top of another
pdf as a watermark/stamp. The output works well with pdftk's multistamp
option. This program requires the output of pdftk's dump command as an
input. This program, with pdftk, is useful for Bates labeling/numbering
pdf documents.
*/

#include <malloc.h>
#include <string.h>
#include <stdio.h>

int pages = 2000;
char location = 'r';
char *prefix = NULL;
int prefix_length = 0;
char *format = NULL;
int digits = 0;
int number = 0;
char *font = NULL;
int font_size = 0;
FILE *pdf = NULL;
FILE *dump_data = NULL;

int prompt(void)
{
        prefix = (char *)malloc(256);
        format = (char *)malloc(256);
        font = (char *)malloc(256);
        printf("Enter location (l)eft, (c)enter, (r)ight: ");
        scanf(" %c", &location);
        if (location!='l' && location!='c' && location!='r') {
                printf("error: location must be l, c, or r\n");
                return 1;
        }
        printf("Enter prefix: ");
        scanf("%s", prefix);
        prefix_length = strlen(prefix);
        if (prefix_length < 0 || prefix_length > 40) {
                printf("error: 0 <= prefix length <= 40\n");
                return 1;
        }
        printf("Enter number format/start, like 0000123: ");
        scanf("%s", format);
        digits = strlen(format);
        if (digits <= 0 || digits > 9) {
                printf("error: 0 < digits <= 9\n");
                return 1;
        }
        number = strtol(format, NULL, 10);
        if (number < 0 || number > 10000000000) {
                printf("error: 0 <= number <= 1000000000\n");
                return 1;
        }
        printf("Enter font size: ");
        scanf("%s", font);
        font_size = strtol(font, NULL, 10);
        if (font_size < 1 || font_size > 100) {
                printf("error: 1 <= font size <= 100\n");
                return 1;
        }
        return 0;
}

int find_number_of_pages(void)
{
        char *line = NULL;
        int size = 16;
        int found = 0;
        line = (char *)malloc(512);
        while (fgets(line, size, dump_data)) {
                if (strncmp(line, "NumberOfPages: ", size) == 0) {
                        if (fgets(line, 32, dump_data)) {
                                pages = strtol(line, NULL, 10);
                                printf("notice: determined %d pages from pdftk dump_data\n", pages);
                                found = 1;
                                break;
                        }
                }
        }
        free(line);
        if (found)
                return 0;
        return 1;
}

int output_pdf_header(void)
{
        fprintf(pdf, "%%%%PDF-1.0\n");
        fprintf(pdf, "1 0 obj\n");
        fprintf(pdf, "<<\n");
        fprintf(pdf, "/Type /Catalog\n");
        fprintf(pdf, "/Pages 3 0 R\n");
        fprintf(pdf, ">>\n");
        fprintf(pdf, "endobj\n");
        fprintf(pdf, "\n");
        fprintf(pdf, "2 0 obj\n");
        fprintf(pdf, "<<\n");
        fprintf(pdf, "/Type /Font\n");
        fprintf(pdf, "/Subtype /Type1\n");
        fprintf(pdf, "/BaseFont /Helvetica\n");
        fprintf(pdf, ">>\n");
        fprintf(pdf, "endobj\n");
        if (fprintf(pdf, "\n") < 0)
                return 1;
        return 0;
}

int output_pdf_pages_object(void)
{
        int page_object;
        int objects = pages * 2 + 3;
        fprintf(pdf, "3 0 obj\n");
        fprintf(pdf, "<<\n");
        fprintf(pdf, "/Type /Pages\n");
        fprintf(pdf, "/Count %d\n", pages);
        fprintf(pdf, "/Kids [\n");
        for (page_object=4; page_object <= objects; page_object +=2)
                fprintf(pdf, "%d 0 R\n", page_object);
        fprintf(pdf, "]\n");
        fprintf(pdf, ">>\n");
        fprintf(pdf, "endobj\n");
        if (fprintf(pdf, "\n") < 0)
                return 1;
        return 0;
}

void output_page_object(int page_object, int stream_object)
{
        fprintf(pdf, "%d 0 obj\n", page_object);
        fprintf(pdf, "<<\n");
        fprintf(pdf, "/Type /Page\n");
        fprintf(pdf, "/Parent 3 0 R\n");
        fprintf(pdf, "/Resources << /Font << /F1 2 0 R >>\n");
        fprintf(pdf, ">>\n");
        fprintf(pdf, "/MediaBox [0 0 612 1008]\n");
        fprintf(pdf, "/Contents %d 0 R\n", stream_object);
        fprintf(pdf, ">>\n");
        fprintf(pdf, "endobj\n");
}

void output_stream_object(int stream_object)
{
        int box_width = (prefix_length + digits) * font_size * 2 / 3;
        int box_location = 20;
        if (location == 'c')
                box_location = 310 - (box_width / 2);
        else if (location == 'r')
                box_location = 594 - box_width;
        int text_location = box_location + font_size / 8;
        fprintf(pdf, "%d 0 obj\n", stream_object);
        fprintf(pdf, "<< /Length 5 >>\n");
        fprintf(pdf, "stream\n");
        fprintf(pdf, "/Artifact <</Attached [/Bottom]/Type/Pagination>> BDC 0.753 g\n");
        fprintf(pdf, "%d 20 %d %d re\n", box_location, box_width, font_size + font_size / 4);
        fprintf(pdf, "f*\n");
        fprintf(pdf, "BT\n");
        fprintf(pdf, "/F1 %d Tf\n", font_size);
        fprintf(pdf, "1 0 0 1 %d %d Tm\n", text_location, 20 + font_size / 4);
        fprintf(pdf, "0 g\n");
        fprintf(pdf, "0 G\n");
        fprintf(pdf, "[(%s%0*d)] TJ\n", prefix, digits, number);
        fprintf(pdf, "ET\n");
        fprintf(pdf, "endstream\n");
        fprintf(pdf, "endobj\n");
        fprintf(pdf, "\n");
}

int output_pdf_page_and_stream_objects(void)
{
        int page_object;
        int stream_object;
        int objects = pages * 2 + 3;
        for (page_object = 4; page_object <= objects; page_object +=2) {
                stream_object = page_object +1;
                output_page_object(page_object, stream_object);
                output_stream_object(stream_object);
                number++;
        }
        if (fprintf(pdf, "\n") < 0)
                return 1;
        return 0;
}

int output_pdf_trailer(void)
{
        int objects = pages * 2 + 4;
        fprintf(pdf, "xref\n");
        fprintf(pdf, "0 %d\n", objects);
        fprintf(pdf, "trailer\n");
        fprintf(pdf, "<<\n");
        fprintf(pdf, "/Size %d\n", objects);
        fprintf(pdf, "/Root 1 0 R\n");
        fprintf(pdf, ">>\n");
        fprintf(pdf, "startxref\n");
        if (fprintf(pdf, "%%%%EOF") < 0)
                return 1;
        return 0;
}

int main(int argc, char **argv)
{
        printf("\n\nGenerating a Bates Labeling/Numbering PDF File\n\n");
        if (argc != 3) {
                printf("usage: %s <pdftkDumpDataFile> <outputPDFfile>\n", argv[0]);
                return 1;
        }
        if (prompt())
                return 1;
        dump_data = fopen(argv[1], "r");
        if (!dump_data) {
                printf("error: could not open %s for reading\n", argv[1]);
                return 1;
        }
        if (find_number_of_pages())
                printf("warning: could not determine number of pages from pdftk dump_data, using %d\n", pages);
        fclose(dump_data);
        pdf = fopen(argv[2], "w");
        if (!pdf) {
                printf("error: could not open %s for writing\n", argv[2]);
                return 1;
        }
        if (output_pdf_header()) {
                printf("error: could not write pdf header\n");
                return 1;
        }
        if (output_pdf_pages_object()) {
                printf("error: could not write page object\n");
                return 1;
        }
        if (output_pdf_page_and_stream_objects()) {
                printf("error: could not write page and stream objects\n");
                return 1;
        }
        if (output_pdf_trailer()) {
                printf("error: could not write pdf trailer\n");
                return 1;
        }
        fclose(pdf);
        return 0;
}

Open in new window

Right now, you pass in 2 args. You want to continue passing in those 2 args plus 3 more, and then validate them like prompt does?
Did you figure this out? Still having any trouble?
I figured out what I needed as far as passing arguments. Where I am stuck, and have moved on, is understanding pointers and variables. I have not used C before and thought this may be easier. I am trying to work it out using c#/asp.net

The end goal was to take the original code https://www.experts-exchange.com/questions/29161040/C-code-to-pass-string-data-from-argv-to-another-function.html?anchorAnswerId=42959933#a42959933 and instead of gathering variables in the prompt() function, have those same variables passed in the command line and parse them from argv and making this a command line program I can call.
Adding the 3 extra args in the command line should just follow my example. Are you having trouble taking that  solution and replacing the prompt with them? Did you give it a try and not working?