This question already has answers here:
What does int argc, char *argv[] mean?
(12 answers)
Closed 1 year ago.
I am writing a code for a Caeser cipher program in C. the code is working as intended however I was trying to edit the code to make it accept multiple arguments instead of just one like it does currently. To incorporate this I added a new array in the main() named argvalue1 to hold the second argument. Furthermore I added a second interating variable and another loop to read the characters from the second array. I am still really new to using C, just not sure why the program will not read the second argument and how I can fix that.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
// Compile this program with:
// cc -std=c11 -Wall -Werror -o rotate rotate.c
#define ROT 13
// The rotate function returns the character ROT positions further along the
// alphabetic character sequence from c, or c if c is not lower-case
char rotate(char c)
{
// Check if c is lower-case or not
if(islower(c)) {
// The ciphered character is ROT positions beyond c,
// allowing for wrap-around
return ('a' + (c - 'a' + ROT) % 26);
}
else {
return c;
}
}
// Execution of the whole program begins at the main function
int main(int argcount, char *argvalue[], char *argvalue1[])
{
// Exit with an error if the number of arguments (including
// the name of the executable) is not precisely 2
if(argcount != 3) {
fprintf(stderr, "%s: program expected 1 argument, but instead received %d\n",
argvalue[0], argcount-1);
exit(EXIT_FAILURE);
}
else {
// Define a variable for a later loop
int i;
int j;
// Calculate the length of the first argument
int length = strlen(argvalue[1]);
int length2 = strlen(argvalue1[1]);
// Loop for every character in the text
for(i = 0; i < length; i++) {
// Determine and print the ciphered character
printf("%c", rotate(argvalue[1][i]));
printf("%c", rotate(argvalue1[1][j]));
}
// Print one final new-line character
printf("\n");
// Exit indicating success
exit(EXIT_SUCCESS);
}
return 0;
}
You don't need to add char *argvalue1[] at all here. Notice that the the second argument char *argvalue[] is actually an array.
The second argument that you run your code with will be part of this array and that is how you should access it within your code.
To reiterate :
argvalue[0] --> first argument
argvalue[1] -- second argument
Related
I am trying to compare two set of data using strcmp. This first set of data are var1 which is get from fgets(var1, 100, stdin). The second set of data are generate randomly by rand. When I complie it, I get two same errors. They both come from char f.
warning: assignment makes pointer from integer without a cast printf(f);
warning:assignment makes pointer from integer without a cast if (strcmp(var1,f)==0)
i already declare the randomly generated number char f = rand() % 38; in char, why will it not work?
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main()
{
char var1[100];
int result;
fgets(var1, 100, stdin);
srand(time(NULL));
char myArray[38] = { 1,5,3,4};
char f = rand() % 38;
printf(var1);
printf(f);
if (strcmp(var1,f)==0) {
result = 1;
printf("It work\n");
}
else {
printf("It didn't work!\n");
result = 0;
}
return 0;
}
EDITED CODE
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
int main()
{
char var1[100];
int result;
scanf("%s",var1);
srand(time(NULL));
char myArray[7] = { 0,28,9,26,30,11,7 };
int randomindex= 1 + (rand() % 100);
char f = myArray[randomindex];
char str_f[2] = { f, '\0' };
printf("var1: %s\n",var1);
printf("%s",str_f);
printf("\n");
if (strcmp(var1,str_f)==0) {
result = 1;
printf("It work\n");
}
else {
printf("It didn't work!\n");
result = 0;
}
return 0;
}
As commented above, in C Langage, functions from Library have a strict format and using not that expected format will occur warning or error at compilation time or runtime.
Function 1 - the printf() is the common function to write C strings to the standard output stdout (declared in <stdio.h>).
See the C library function - printf()
int printf(const char *format, ...)
In the provided source code, the printf() function has been used in the following cases:
printf("It work\n"); to write a fixed string which complies with the const char * expected format of the first parameter ==> OK,
printf(var1); to write the content of the entered string var1 (declared as char var1[100];) which not exactly complies with const char * of the first parameter but will be cast during compile time. A proposed format to write the var1 string could be printf("%s",var1); (or more verbose printf("var1: %s",var1);) where the first parameter "%s" will specify that the following argument var1 will be a string.
printf(f); to write the content of the random value (declared as char f;) which doesn't comply with const char * of the first parameter and doesn't compile at all. The minimal expected format to write the f character is printf("%c",f); (or more verbose printf("f=%c",f);) where the first parameter "%c" will specify that the following argument f will be a character.
Function 2 - the strcmp() is a function to compare two C strings parameters (declared in <string.h>.
See the C library function - strcmp()
int strcmp(const char *str1, const char *str2)
In the provided source code, the strcmp() function has not been used as specified. The function expects two input parameters:
First parameter of strcmp(var1,...)==0 is var1 (declared as char var1[100];) which not exactly complies with const char * but will be cast during compile time.
Second parameter of strcmp(...,f)==0 is f (declared as char f;) which doesn't comply with const char * and doesn't compile at all.
To compare the character f with var1, it shall be necessary to
convert it to a string (In C, a string is an array of char ended by
a character).
Solution 1 - how to convert the character char f; to a string.
A C string is an array of characters: char str_f[]= { '<char>', ... , '<NUL>' };. Meaning that a minimal array of 2 characters is necessary to convert the character char f; to a string.
char f = rand() % 38;
// use a 2 characters string
char str_f[2] = { f, '\0' };
// Could be also initialised as str_f[0] = f; str_f[1] = '\0';
// compare the strings using `str_f`
if (strcmp(var1,str_f)==0) {
Warning 1 - be careful to the random value range.
When printing characters, a C string is supposed to be filled by ASCII
characters different from which is used to end the string.
In the provided source code, the assignment of f, char f = rand() % 38;, will generate values from 0 to 37 which include the character and the first 31 non-printable characters (ctrl-characters). Only characters greater than 31 will be displayed.
In will be more easy to generate: char f = ' ' + (rand() % 38);
where ' ' is the first printable ASCII character = 32.
I'm just toying with the
int main(int argc, int *argv[void])
function, and im trying to make a program that reads the number of number arguments.
Theoretically (in my own crazy delusional mind), this should work:
#include <stdio.h>
int main(int argc, char *argv[])
{
int count;
printf("%d\n", sizeof(int));
}
but no matter what i put as the argument in the command line, i always get 4 (4 bytes in a word?)
How can I tweak this code a little so that when i type
./program 9 8 2 7 4 3 1
i get:
7
much appreciated!
argc represents the number of command line arguments passed in. You can use that as an index into the second argument to main, argv. If you want all the arguments not including the first one (the program name), then you'll need to decrement argc, and increment argv.
#include <stdio.h>
#include <errno.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
/*
* forget about the program name.
*/
argv++;
argc--;
int i;
unsigned int totalNumbers = 0;
printf("Total number of arguments: %d\n", argc);
for(i = 0; i < argc; i++) {
printf("argv[%d]=%s\n", i, argv[i]);
errno = 0;
long num = strtol(argv[i], NULL, 10);
if(!(num == 0L && errno == EINVAL))
totalNumbers++;
}
printf("Total number of numeric arguments: %u\n",
totalNumbers);
return 0;
}
As others have pointed out in the comments, sizeof doesn't do quite what you think it does.
You are given argc and argv. The second of these is an array of string corresponding to the things on the command line. This argv array of strings is argc long, and the first element of it is likely to hold the name of the executable program.
You need to loop through the remaining elements of argv (if there are any) and see which ones are numbers, as opposed to non-numbers.
To check if a string is a number or not, we can use strtol() (from stdlib.h) to try to convert it into a long. If the conversion fails, it's not a number. If you'd like to accept floating point values, then use strtod() instead, it works almost in the same way (doesn't take the last argument that strtol() does). EDIT: I actually changed the code to use strtod() instead since it accepts a larger variety of "numbers".
The conversion fails if the string is empty from the start, or if the pointer that we supply to the function (endptr) doesn't point to the very end of the string after calling it.
Then, if the argument is a number, simply count it, and at the end tell the user what he or she probably already knew.
What you're doing here is called validating user input and it's a really good thing to know how to do. Don't trust users to give you numbers just because you ask them to. Check to see if they really are numbers by reading in strings and trying to convert them.
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
bool is_number(const char *string)
{
char *endptr;
strtod(string, &endptr);
return (*string != '\0' && *endptr == '\0');
}
int main(int argc, char **argv)
{
int i;
int numcount = 0;
for (i = 1; i < argc; ++i) {
if (is_number(argv[i]))
numcount++;
}
printf("There were %d numbers on the command line\n", numcount);
return EXIT_SUCCESS;
}
Running it:
$ /a.out 1 2 3 a b c -.5 +20 1e20
There were 6 numbers on the command line
$ ./a.out nt 12 ,e2 2 21n 1 -8
There were 4 numbers on the command line
i am writing a basic c program to display two strings, one taken from user i.e "a" and the other being defined in code "b" but when i run the code below string "a" gets appended to "b". why? and what is that symbol at end of "a"
updated code:
#include <stdio.h>
#include <string.h>
int main()
{
char a[ 5 ];
int i=0;
while(i<5)
{
a[i]=getchar();
i++;
}
char b[]={'r','f','s','/0'};
printf("output:-");
printf("\n %s",a);
printf("\n %s",b);
return 0;
console
qwert
output:-qwert$
rfs$qwert$
there is a some special symbol instead of $ above, what is it?
Putting all the comments into an answer. The problems in the original code stem mostly from not NUL terminating the character arrays to produce valid C strings.
a is not NUL terminated. Can fix by increasing the a array by 1 and explicitly writing a NUL to the last byte.
b is not NUL terminated. Can fix by initialising b using a literal string or a char array with '\0' as the last byte. The example below uses the former.
Here is the full code with the errors corrected. Note that the code to read input is fragile as it only accepts exactly a 5 character string.
#include <stdio.h>
#include <string.h>
int main(void)
{
char a[6];
int i=0;
while (i<5) {
a[i]=getchar();
i++;
}
a[i] = '\0';
char b[]="rfs";
printf("output:-\n");
printf(" %s\n",a);
printf(" %s\n",b);
return 0;
}
I am new to programing in C (only 2 weeks into it). I am unable to figure out why my code is throwing a segmentation fault. I am able to get the program to work if I set long int num equal to a static number. However I need the program to be able to accept user input from the command line (not once the program is running)
Example:
./binary 7
should output
The binary number for 7 is: 111
I have tried using strcpy(num, argv[0]) but that also throws errors when compiling.
#include<stdio.h>
#include <string.h>
#include<math.h>
void decToBinary(long int num) // Function Definition
{
long int remainder[50];
int i=0;
int length=0;
printf("The binary number for %d is: ",num);
while(num > 0)
{
remainder[i]=num%2; // does the mod function
num=num/2; // Divides original number by 2
i++; // Increases count for the upcoming for-loop
length++; // Increases length display digits
}
for(i=length-1;i>=0;i--) // Prints out the binary number in order (ignoring the previous 0's)
{
printf("%ld",remainder[i]);
}
printf("\n"); // Adds a new line after the binary number (formatting)
}
//================================================================================================
int main(char argc, char* argv[])
{
long int num; //HOW DO I TAKE ARGV[0] AND MAKE IT A USEABLE VARIABLE???
printf("Enter the decimal number: "); //TEMPORARY until problem above is solved
scanf("%ld",&num); //TEMPORARY until problem above is solved
decToBinary(*num); // Calling decToBinary function
return 0; // Program terminated successfully
}
Hint1: If you want to change num's value inside decToBinary() function, you have to pass its address in it. So you should call it like this:
decToBinary(&num);
Then your function's prototype would look like this:
void decToBinary(long int *num)
So you have to modify the function's body properly too. I guess that's what causes the Segmentation Fault.
Hint2: argc stands for arguments count, so its type isn't char but int.
As #Kerrek SB pointed out on his comments, scanf(3) is a function with a return value of type int. It's considered wise to check the return value and handle any possible error that may occur.
argv[0] is the name of the executable. If you want to use the first argument from your command line, it's stored in argv[1], and it's of type char *. So if you want to use it as a number, you can use one of these functions of stdlib.h.
Something like (does not handle some error situations)
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
void decToBinary(long int num) // Function Definition
{
long int remainder[50];
int i=0;
int length=0;
printf("The binary number for %ld is: ", num);
while(num > 0)
{
remainder[i]=num%2; // does the mod function
num=num/2; // Divides original number by 2
i++; // Increases count for the upcoming for-loop
length++; // Increases length display digits
}
for(i=length-1;i>=0;i--) // Prints out the binary number in order (ignoring the previous 0's)
{
printf("%ld",remainder[i]);
}
printf("\n"); // Adds a new line after the binary number (formatting)
}
//================================================================================================
int main(int argc, char* argv[])
{
if (argc > 1)
{
long int mylong = atol(argv[1]);
decToBinary(mylong); // Calling decToBinary function
} else
{
int errno = 0;
long int num;
int res;
printf("Enter the decimal number: "); //TEMPORARY until problem above is solved
res = scanf("%ld",&num); //TEMPORARY until problem above is solved
if (res != EOF)
{
decToBinary(num); // Calling decToBinary function
} else
if (errno != 0)
{
perror("scanf");
} else
{
printf("No number found in input\n");
}
}
return 0; // Program terminated successfully
}
** I'm building this on Ubuntu 14.04 **
Note that decToBinary(*num) is wrong. You would only use the dereference operator on a pointer not an int or any non pointer type.
A pointer holds an address in memory and when you dereference it you are telling your program to read at that address. If you were dereferencing an int value of for example 10, you are telling the program to read a value at address 10. This is a very low address value and will be outside of the memory range that your programme is allowed to access and so it will be a segmentation fault.
Firstly you must pay attention to compiler warnings. If applicable use the -Werror and possibly -Wextra flags when you build your executable.
e.g
gcc -g -Werror -Wextra myfile.c -o myfile
This is a good opportunity to learn to use a debugger to find your segfault, if you are serious about C programming its essential knowledge. Note above the -g flag which builds debug symbols into your executable (without the symbols the debugger wont know the function names). You can then use gdb (or another debugger as applicable) and launch your executable, then run it and get a back trace to tell you when the segfault happens.
A simple method of extracting the argv[1] parameter to its constituent bits and displaying those bits...
// following eliminates any nonnumeric char from input
// by stopping at first nonnumeric char
long int value = atol(argv[1]);
int position = sizeof( long int ) -1;
// following loop could be modified/prefixed with a loop to skip leading 0's
for( ; position >= 0; position-- )
{
printf( "%c, ", ('0' + ( value >> position) & 1) );
}
printf( "\n" );
I think my problem with my code that the file is not being passed correctly. The input is a file with three lines
1 2 3;
4 5 6;
7 8 9;
and the output is a Segmentation fault (core dumped), the output is supposed to print the first line 1 2 3.
#include <stdio.h>
#include <stdlib.h>
int getNum();
int getLine();
int getMatrix();
int det1();
int det2();
int det3();
int det4();
int det5();
int det6();
main(){
FILE *infile;
infile = fopen("matrix.txt","r");
int line[6];
int lineSize;
int error;
getLine(line,lineSize,infile);
printf("%d %d\n", line[0],line[1]);
fclose(infile);
}
/***********************************************
Name : getLine
Description : To get the line of numbers
Arguments : infile - the file pointer with numbers inside
line[] - the line of numbers
lineSize - size of line
Returns : 1 - If no errors were encountered
2 - If END OF FILE was reached
-1 if non number detected
*************************************************/
int getLine(int line[], int lineSize, FILE *infile){
int value;
int l;
lineSize=0;
while(value != '\n'){
value=0;
l=getNum(value,*infile);
if (value==EOF){
return(2);
}
line[lineSize]=value;
lineSize++;
}
if (l == -1){
return(-1);
}
return(1);
}
/***********************************************
Name : getNum
Description : To get the Next number from file
Arguments : infile - the file with numbers inside
value - the value of number grabed
Returns : 1 - If no errors were encountered
-1 - If letter or non number detected
*************************************************/
int getNum(int value, FILE *infile){
int c;
int error=1;
while ((c=getc(infile)) != EOF){
if (c=='\n'){
value = '\n';
return(1);
}
if(c==32){//checking for space
if (error == -1){
return(-1);
}
else{
return(1);
}
}
else {
value = 10*value + c - '0';
}
if((c<=47)||(c>=58)){
printf("incorrect number input %d\n",c);
error = -1;
}
}
value = EOF;
return(1);
}
Skimming your code ...
int getNum();
int getLine();
int getMatrix();
int det1();
/* ... */
These declarations say to the compiler: "hey compiler, please be aware I'll be calling functions with these names (getNum, getLine, getMatrix, det1, ...) and they return int, but I'm not telling you what parameters they accept. Just trust me when I use them"
It's better if you use the prototype right when you introduce the functions to the compiler
int getNum(int value, FILE *infile);
int getLine(int line[], int lineSize, FILE *infile);
/* ... */
These declarations say to the compiler: "hey compiler, please be aware I'll ba calling function with these names, they return int and accept these parameters. If I make a mistake, do complain to let me know of my mistake"
... continuing inside main()
/* ... */
int lineSize;
int error;
getLine(line,lineSize,infile);
/* ... */
you declared lineSize but didn't provide a value for the variable. When the program calls getLine, the value for lineSize is almost certainly the wrong value (it might even make your computer crash even before calling the function). Initialize (almost) all variables before using them.
/* ... */
int lineSize = 0;
int error = 0;
getLine(line,lineSize,infile);
/* ... */
I haven't skimmed more ...
Suggestion: crank up your compiler warning level and do not run your program while compilation produces warnings.
In getLine(), when you give the infile FILE* to the getNum() function, you dereference it:
l=getNum(value,*infile);
But getNum() would just expect a normal FILE*, not a dereferenced one. So pass infile to that function unchanged:
l=getNum(value,infile);
Additionally, the while(value != '\n') loop will probably run forever, writing past the end of the lines array until you get a segmentation fault. value, which is controlling when the loop will terminate, is never modified (also it isn't initialized, making it start with an arbitrary value). The getNum() function, which probably is supposed to modify value, gets a copy of the integer passed as a parameter and then modifies this copy. The original value is never changed.
If you want the function to change the value variable you have to use a pointer that points to value and that is used to modify that variable:
int getNum(int *value, ...) {
*value = 5;
...
}
l=getNum(&value, infile);
Also it is a little dubious that value, an integer variable, is assigned and compared against '\n', a character literal. Are you sure you want to use the integer value of '\n' as a termination condition of your loop?
While not a direct answer, I'd recommend sticking a number of printf statements in at random spots; that will let you narrow down the exact point of the crash relatively quickly. Move them around until you have two printfs bracketing a single line of code that you then know to be the crashing culprit, which will let you diagnose better.