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" );
Related
I was writing this program:
"program takes a number from the command prompt, and it returns the length of the hailstone sequence".
the hailstone sequence is defined as follows:
if the number is even, then halve the number (n / 2).
if the number is odd, then triple the number, and add one
(3 * n + 1).
if the sequence reaches 1, then the algorithm is stopped.
I have written the code this way (note that at the end of each number there must be a comma and after the comma a space, therefore I've printed them like that):
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* argv[]) {
if (argc != 2) {
return -1;
}
if (argv[1] <= 0) {
return 0;
}
int n = strtod(argv[1], NULL);
int length = 0;
while (n == 1) {
if (n % 2 == 0) {
n /= 2;
printf("%d%s", n, ",");
++length;
printf("%s", " ");
}
else {
n = (3 * n) + 1;
printf("%d%s", n, ",");
++length;
printf("%s", " ");
}
}
return length;
}
I've two errors:
while using strtod function, the debugger warned me "conversion from double to int: possible loss of data". why? argv doesn't contain double, but it's a string. And strtod converts between string to decimal; am I wrong?
I typed in the terminal "hailstone 3". but the terminal doesn't recognise the command. So I've typed only 3, but the terminal returns 3, without any calculations.
EDIT: I've edited my code like that: int main(int argc, char* argv[]) {
int n = strtol(argv[1], NULL, 10);
if (n <= 0) {
return 0;
}
so, basically, I've used the strtol function and after that I've put the if statement because with that I work with a variable (n) instead of working with string (and I think it's way easier). But nothing changed. (I still have the command line problem, but I no longer have the warning).
strtod is used to convert decimal values, the warning tells you that converting a value to double, and assigning it to an int will result in a loss of the fractional part of the assigned value, in this case nothing would result of it, but you should use strtol instead, anyway.
In your code, since argv[1] is a string and you are comparing it to an int value 0, the comparison is not correct, use the aforementioned strtol, or compare it to a string, e.g. const char* str = "0" with something like strcmp(argv[1], str), though I would prefer the first method.
As for the program launch, try ./hailstone 3, assuming you give your executable to your program when you compile the source code.
For example, say your compiler is gcc, you'd have to use something like gcc -o hailstone source.c where source.c would be the name of the source code file.
Using Visual Studio IDE, the build result will not be in the project root, you need to navigate to the folder where the file is.
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
I have a case in which I have to identify if a number is positive, negative or zero and count how many times each of these cases happen. The code I wrote is this:
#include
#include
#include
using namespace std;
int main(int argc, char *argv[])
{
char opcion = 's';
int positivos = 0;
int negativos = 0;
int ceros = 0;
//int ceros2 = 0;
int temporal;
do{
printf("Enter a number: ");
scanf("%d",&temporal);
if(temporal >= 0)
{
if(temporal==0)
{
ceros ++;
}
else
{
positivos ++;
}
}
if(temporal < 0)
{
negativos ++;
}
printf("Do you want to enter another number? (s/n)");
scanf("%s",&opcion);
}
while(opcion == 's' || opcion=='S');
printf("you have %d possitive numbers \n",positivos);
printf("you have %d negative numbers \n",negativos);
printf("you have %d zero \n",ceros);
return 0;
}
If I run the code as it is, the number of zeroes will always be zero, but if you uncoment the line 13 int ceros2 = 0; (my logic was "let's declare another initializaed variable and see what happens") then the program will count the zeroes as expected. Why do i have to declare a useless variable in order to the program make the count?
What is C compiler doing with the code that does not respect the value of the last declared and initialized variable unless you declare a new initialized variable?
You are asking scanf() to read in a C string, which, if the user types a character, will contain both that character and the null terminator. You have provided only a single character's worth of storage. So, the null terminator doesn't fit but it gets stored somewhere. As it happens, it's clobbering other data that happens to be next to opcion on the stack and that happens to be your ceros variable.
Declaring another variable has reorganized the layout of data on the stack and changes what gets clobbered, so you're not noticing it. It's still writing out of bounds, though.
You could use a format string of "%c" to read a single character.
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 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.