Scott Fell
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.
Below will throw, "warning C4477: 'printf' : format string '%s' requires an argument of type 'char *', but variadic argument 1 has type 'int'"
My end goals are to be able to something like
or
The original code that goes with with this added in the function() that tested.
I
#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;
}
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);
If I change toprintf("prefix=%c\n", prefix);
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;
}
or
if(prefix == 'xxxyyy')
{
return 1;
}
else
{
return 0;
}
The original code that goes with with this added in the function() that tested.
prefix = (char *)malloc(256);
I
ASKER CERTIFIED SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
SOLUTION
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
ASKER
Microsoft (R) C/C++ Optimizing Compiler Version 19.20.27508.1 for x86
ASKER
This seems to be working
What does memory allocation add here with,
#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;
}
What does memory allocation add here with,
prefix = (char *)malloc(256);
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.
ASKER
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.
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;
}
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?
Did you figure this out? Still having any trouble?
ASKER
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.
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?
int function(location, font_size, prefix)
Is this C99?