"Debug assertion failed! expression: _p != nullptr" error - c

error imageI tried to make a program that does calculation with multiple arguments.
Everything works as I intended except for last one in the picture i attached.
Every time I try to put more than 2 numbers in the command line, the error occurs.
The example of input is this : program1.exe 12 + 13 - 2 + 1
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[])
{
int a, b, rst;
int i;
char opr;
if (argc > 100)
{
printf("Too many arguments!\n");
return 0;
}
else if (argc <= 1)
{
printf("There are no arguments!\n");
return 0;
}
a = atoi(argv[1]);
rst = a;
if (argc == 2)
{
a = atoi(argv[1]);
}
else if (argc % 2 != 0)
{
printf("Invalid fomula!\n");
exit(0);
}
else
{
for (i = 1; 2*i <= argc; i++)
{
b = atoi(argv[2 * i]);
opr = argv[2 * i - 1];
switch (opr)
{
case '+':rst = a + b;
break;
case '-':rst = a - b;
break;
}
rst = a;
}
}
printf("%d", rst);
return 0;
}

Running the code as is, with input set to: <program.exe> 2 + 5
a null pointer error occurs here:
for (i = 1; 2*i <= argc; i++)
{
b = atoi(argv[2 * i]);//Null pointer for i==2
opr = argv[2 * i - 1];
switch (opr)
because there is no argv[4]. This results in undefined behavior.
It is impossible to make corrections accurately without knowing what the program expects as input. Because you do not specify, my best guess is the program attempts to read a set of arguments from the command line, eg:
argv[0] argv[1] argv[2] argv[3]
<program>.exe 1 + 2
Then convert the values read into variables, and perform a math operation using two numerics and a math operator such as + or -.
Assuming this is the basic goal, the following example simplifies your existing code to perform these steps. Note corrections to the argument input count test, and lower down, the looping indexes:
#include <stdio.h>
#include <stdlib.h>
/// test using:
// prog.exe 2 + 3 3 - 4 6 + 7
//results are:
//result 0: 5
//result 1: -1
//result 2: 13
typedef struct {
int n1;
char opr;
int n2;
int result;
} CALC;
int main(int argc, char *argv[])
{
int i;
// test for correct number of input arguments
if((argc-1)%3 !=0)
{
printf("Wrong number of inputs.\n");
return 0;
}
// read in, and assign variables (use array of struct)
int max = (argc-1)/3; //guaranteed viable only after determining multiples are correct from above
//Get ALL input into array variables
CALC calc[max];
for (i=0;i<max;i++)
{
//convert inputs into usable variables
calc[i].n1 = atoi(argv[i*3+1]);
calc[i].opr = argv[i*3+2][0];
calc[i].n2 = atoi(argv[i*3+3]);
// perform calulations
switch(calc[i].opr) {
case '+':
printf("result %d: %d\n", i, calc[i].n1 + calc[i].n2);
break;
case '-':
printf("result %d: %d\n", i, calc[i].n1 - calc[i].n2);
break;
}
}
return 0;
}
Most error checking, and testing of function return values are left to you.

Related

input files in C

Code implements the dynamic programming solution for global pairwise alignment of two sequences. Trying to perform a semi-global alignment between the SARS-CoV-2 reference genome and the first read in the Nanopore sample. The length of the reference genome is 29903 base pairs and the length of the first Nanopore read is 1246 base pairs. When I run the following code, I get this message in my terminal:
Usage: align < input file >
How do I add the necessary files to the code. The file names are SARS-CoV-2 reference genome.txt and Nanopore.txt, where A = SARS-CoV-2 reference genome.txt file and B = Nanopore.txt file
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define GAP -2
#define MATCH 5
#define MISMATCH -3
#define MAXLENGTH_A 29904
#define MAXLENGTH_B 1247
int max(int A, int B, int C)
{
if (A>=B && A>=C) return A;
else if (B>=A && B>=C) return B;
else return C;
}
char Tmax(int A, int B, int C)
{
if (A>B && A>C) return 'D';
else if (B>A && B>C) return 'L';
else return 'U';
}
int m(char p, char q)
{
if (p==q) return MATCH;
else return MISMATCH;
}
void append(char *st,int L,char c)
{
int i;
for (i=L;i>0;i--)
st[i]=st[i-1];
st[L+1] = '\0';
st[0] = c;
}
int main(int argc, char **argv)
{
FILE *fp;
char A[1000];
char B[1000];
char RA[1000];
char RM[1000];
char RB[1000];
int N,M,L;
int i,j;
//int S[MAXLENGTH_A][MAXLENGTH_B];
//char T[MAXLENGTH_A][MAXLENGTH_B];
int **S;
char **T;
S = (int**)malloc(sizeof(int*)*MAXLENGTH_A);
for (int i = 0; i<29904; i++)
S[i] = (int*)malloc(sizeof(int)*MAXLENGTH_B);
T = (char**)malloc(sizeof(char*)*MAXLENGTH_A);
for (int i = 0; i<29904; i++)
T[i] = (char*)malloc(sizeof(char)*MAXLENGTH_B);
if (argc!=2)
{
printf("Usage: align <input file>\n");
exit(1);
}
fp = fopen(argv[2],"r");
if (fp==NULL)
{
printf("input file not found.\n");
exit(1);
}
fscanf(fp,"%s",A);
fscanf(fp,"%s",B);
printf("Sequence A: %s\n",A);
printf("Sequence B: %s\n",B);
N = strlen(A);
M = strlen(B);
S[0][0] = 0;
T[0][0] = 'D';
// initialize first column
for (i=0;i<=N;i++)
{
S[i][0] = GAP*i;
T[i][0] = 'U';
}
//initialize the firt row
for (i=0;i<=M;i++)
{
S[0][i] = GAP*i;
T[0][i] = 'L';
}
for (i=1;i<=N;i++)
for (j=1;j<=M;j++)
{
S[i][j] = max(S[i-1][j-1]+m(A[i-1],B[j-1]),S[i][j-1]+GAP,S[i-1][j]+GAP);
T[i][j] = Tmax(S[i-1][j-1]+m(A[i-1],B[j-1]),S[i][j-1]+GAP,S[i-1][j]+GAP);
}
printf("The score of the alignment is : %d\n",S[N][M]);
i=N;
j=M;
L=0;
RA[0]='\0';
RB[0]='\0';
RM[0]='\0';
while (i!=0 || j!=0)
{
if (T[i][j]=='D')
{
append(RA,L,A[i-1]);
append(RB,L,B[j-1]);
if (A[i-1]==B[j-1]) append(RM,L,'|');
else append(RM,L,'*');
i--; j--;
}
else if (T[i][j]=='L')
{
append(RA,L,'-');
append(RB,L,B[j-1]);
append(RM,L,' ');
j--;
}
else if (T[i][j]=='U')
{
append(RA,L,A[i-1]);
append(RB,L,'-');
append(RM,L,' ');
i--;
}
L++;
}
printf("%s\n",RA);
printf("%s\n",RM);
printf("%s\n",RB);
}
These lines of the program
printf("Usage: align <input file>\n");
/* AND */
fp = fopen(argv[2],"r");
/* AND */
fscanf(fp,"%s",A);
fscanf(fp,"%s",B);
show the program expects to read from one file.
From your question, it seems you could make a third data file with one line containing the 29903 characters without spaces or breaks of the first sequence followed by a second line containing 1246 characters (again continuous characters) of the second sequence. But, don't do this...
When the program is run (eg: ./a.out filename) and one supplies the name of the 'combined' file, the first fscanf() will attempt to load the first block of characters into the array named 'A'. The second fscanf() would load the second block into the array named 'B'.
This is a problem because both 'A' and 'B' are dimensioned to hold only 1000 bytes each, maximum...
As this code is right now, you cannot use it to load the long sequences you want to. Sorry.

Why does the number get ignored?

I want to write a very simple calculator in C.
At the start, the variable for the output is 0 and every calculation adjusts the value.
For example if I type -a 5 at the program start the output is 5, if I write -a 5 -s 5 the output is 0.
If I don't choose a or s it will just add all values to the output.
And if I type something like -a 10 -s 5 10 25, the 10 and 25 also should be add to the output.
This is my code so far:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
int result = 0;
for (int i = 1; i < argc - 1; i++) {
for (int j = i + 1; j < i + 2; j++) {
int value = atoi(argv[j]);
if (strcmp(argv[i], "-a") == 0) {
result += value;
} else
if (strcmp(argv[i], "-s") == 0) {
result -= value;
} else {
result += value;
}
}
}
printf("%d\n", result);
return 0;
}
All works fine, but not when I just type in some numbers without -s or -a.
When I start the program for example with 5 10 25, it will ignore the first number and the output will be 35. I don't really know, how to fix this.
Problems:
The first argument will never be treated as value inside of your program because j in int value = atoi(argv[j]); will ever start with the value of 2, not 1. j is declared and initialized with int j = i + 1; (j gets initialized with the value of i plus one) and since i starts with the value of 1 (int i = 1), j will start with a value of 2.
The inner loop isn't needed at all and literally only mess things up as it is even the source of your main issue already and makes your code harder to read. I highly recommend you to omit it.
For value: Declaring a variable inside a loop isn't a good practice BTW because the variable is declared new at each iteration. A compiler can optimize this but just avoid it.
Also a problem is that you convert the string arguments of -a and -s into an int value with this because you use the conversion before checking the values of the arguments. Note that used in the right way (when the conversion is only done based on a value argument) we don't need the variable value at all.
You can simplify the code like that:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main (int argc, char *argv[]) {
int result = 0;
for (int i = 1; i < argc; i++) {
if ( strcmp(argv[i], "-a") == 0 && i + 1 < argc && strcmp("-s", argv[i+1]) && strcmp("-a", argv[i+1]) ) {
result += atoi(argv[i+1]);
i++; // We use the next argument already here, so go forward.
}
else if ( strcmp(argv[i], "-s") == 0 && i + 1 < argc && strcmp("-s", argv[i+1]) && strcmp("-a", argv[i+1]) ) {
result -= atoi(argv[i+1]);
i++; // We use the next argument already here, so go forward.
}
else {
result += atoi(argv[i]);
}
}
printf("%d\n", result);
return 0;
}
Execution
Your example:
./calculator -a 10 -s 5 10 25
40
My example:
./calculator 10 34 -a 6 -s 4 25 -a 19 5 -s 24
71
Have fun at proof if the calculation is correct. ;-)
Or just try it online.
The problem with your code is that argv[1] is only tested to be either -a or -s but there is no code that converts argv[1] to a number and adds it to the result.
You need to handle all 3 cases in the loop, i.e. case 1 "-a", case 2 "-s" and case 3 "a number".
This could be like:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
int result = 0;
int i = 1;
while (i < argc) {
if (strcmp(argv[i], "-a") == 0) {
// Case 1
++i; // Increment i to move to next argument
if (i == argc) break; // Check that there is a valid argument
int value = atoi(argv[i]);
result += value;
} else
if (strcmp(argv[i], "-s") == 0) {
// Case 2
++i;
if (i == argc) break;
int value = atoi(argv[i]);
result -= value;
} else {
// Case 3 Current argument is (expected to be) a number
int value = atoi(argv[i]);
result += value;
}
++i; // Move to next argument
}
printf("%d\n", result);
return 0;
}
The above code uses atoi like the code in the question. A down-side of atoi is that there is no input validation, i.e. it's not validated that the string is actually a number.
For better input validation consider using strtol instead of atoi.
Your program does not seem to implement a solution to the problem:
You should keep track of the current mode ie: adding or subtracting and handle each argument accordingly (resetting the mode after each number handled).
Your nested loop ignores the first of 2 arguments. It also ignores the argument if only one is provided.
Here is a modified version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[]) {
int result = 0;
int mode = 1;
for (int i = 1; i < argc; i++) {
if (!strcmp(argv[i], "-a")) {
mode = 1;
} else
if (!strcmp(argv[i], "-s")) {
mode = -1;
} else {
char *p;
int value = strtol(argv[i], &p, 0);
if (p == argv[i] || *p != '\0') {
printf("invalid argument: %s\n", argv[i]);
} else {
result += mode * value;
}
mode = 1; // only subtract a single argument
}
}
printf("%d\n", result);
return 0;
}
Note that the above program detects invalid input but does not detect nor handle arithmetic overflow.

adding a 0 to an array of char* based on the argc being even or odd

so I'm working on an assignment where the user simply calls the parent.c class like "./parent 1 2 3 4 5 6 7 8" and the child.c class will compute the sum of the result.
It works by reading 2 numbers each on the line like this...
"1 + 2" "3 + 4" "5 + 6" "7 + 8"
I've gotten it to do this successfully, but I hit a complete brick wall when the input ends up being odd. As I keep looping the child processes, each 2 numbers will keep adding up, but it becomes a problem when the loop comes to the end of the input and there are no longer 2 numbers to add, but simply one (odd number scenario).
So if the input became something such as...
"./parent 1 2 3 4 5 6 7" or "./parent 1 2 3"
it will just flat out return as 0.
My file will compute the even numbers, but it will not add up an odd amount of numbers. The overall goal I would like to accomplish is to just be able to add a zero if the input ever hits an odd number. One attempted solution I had was to just check at the beginning of the while loop if the amount of values in data array was odd, and then increment index by one and then add a 0 to that very index. But it still didn't provide the correct solution.
parent.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <math.h>
int main(int argc, char *argv[])
{
int status, workerid, id;
int i = 0;
int loopcount = 0;
char* data[argc];
for(i = 1; i <= argc; i++)
{
data[i] = argv[i];
}
int numberloops = argc / 2;
int index = 0;
while(numberloops > index)
{
loopcount = 0;
for(i = 1; i <= argc; i += 2)
{
loopcount++;
id = fork();
if(id < 0)
{
perror("fork() ERROR.\n");
}
else if(id > 0)
{
workerid = waitpid(id, &status, 0);
status = WEXITSTATUS(status);
//update data array
char* statStr;
statStr = (char*) malloc(16);
snprintf(statStr, sizeof(statStr), "%d", status);
data[loopcount] = statStr;
}
else
{
execlp("./child", "child", data[i], data[i+1], NULL);
}
}
int arrayNum = atoi(data[loopcount]);
// Adds a 0 to the array.
while(loopcount < argc)
{
loopcount++;
data[loopcount] = 0;
}
//change argc (number of values in data array)
if(argc % 2 == 1)
{
argc = (argc + 1) / 2;
}
else
{
argc /= 2;
}
index++;
}
printf("Final Sum: %s.\n\n", data[1]);
}
child.c
#include<stdio.h>
#include<stdlib.h>
int main(int argc, char *argv[])
{
int x = atoi(argv[1]);
int y = atoi(argv[2]);
int sum = x + y;
printf("%d + %d = %d Worker PID: %d\n", x, y, sum, getpid());
exit(sum);
}
To get around the "odd-issue" one simple approach would be to define char * data[argc + 1]; and initialise all it's elements to point to a literal "0" before setting the relevant elements to point to argv's elements.
It seems to me you are making the code much more complicated than need. Some specific items:
1) Why do you have two nested loops (i.e. a while with a for inside)? As far as I can see that will just lead to too many calls of child
2) workerid seems unused!?
3) arrayNum seems unused!?
4) Why convert the return values into strings? You want to calculate a sum so just keep it as integer
Simplifying your code could give something like:
#include <stdio.h>
#include <unistd.h>
#include <sys/wait.h>
int main(int argc, char *argv[])
{
int status, id;
int i = 1;
int sum = 0;
int numberloops = argc / 2;
int index = 0;
while(numberloops > index)
{
id = fork();
if(id < 0)
{
perror("fork() ERROR.\n");
}
else if(id > 0)
{
waitpid(id, &status, 0);
status = WEXITSTATUS(status);
sum += status;
}
else
{
if (i == argc-1)
{
execlp("./child", "child", argv[i], "", NULL);
}
else
{
execlp("./child", "child", argv[i], argv[i+1], NULL);
}
}
i = i + 2;
index++;
}
printf("Final Sum: %d.\n\n", sum);
}
Example:
./parent 1 2 3 4 5
1 + 2 = 3 Worker PID: 12961
3 + 4 = 7 Worker PID: 12962
5 + 0 = 5 Worker PID: 12963
Final Sum: 15.

Decimal to Binary conversion not working

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
int myatoi(const char* string) {
int i = 0;
while (*string) {
i = (i << 3) + (i<<1) + (*string -'0');
string++;
}
return i;
}
void decimal2binary(char *decimal, int *binary) {
decimal = malloc(sizeof(char) * 32);
long int dec = myatoi(decimal);
long int fraction;
long int remainder;
long int factor = 1;
long int fractionfactor = .1;
long int wholenum;
long int bin;
long int onechecker;
wholenum = (int) dec;
fraction = dec - wholenum;
while (wholenum != 0 ) {
remainder = wholenum % 2; // get remainder
bin = bin + remainder * factor; // store the binary as you get remainder
wholenum /= 2; // divide by 2
factor *= 10; // times by 10 so it goes to the next digit
}
long int binaryfrac = 0;
int i;
for (i = 0; i < 10; i++) {
fraction *= 2; // times by two first
onechecker = fraction; // onechecker is for checking if greater than one
binaryfrac += fractionfactor * onechecker; // store into binary as you go
if (onechecker == 1) {
fraction -= onechecker; // if greater than 1 subtract the 1
}
fractionfactor /= 10;
}
bin += binaryfrac;
*binary = bin;
free(decimal);
}
int main(int argc, char **argv) {
char *data;
data = malloc(sizeof(char) * 32);
int datai = 1;
if (argc != 4) {
printf("invalid number of arguments\n");
return 1;
}
if (strcmp(argv[1], "-d")) {
if (strcmp(argv[3], "-b")) {
decimal2binary(argv[2], &datai);
printf("output is : %d" , datai);
} else {
printf("invalid parameter");
}
} else {
printf("invalid parameter");
}
free(data);
return 0;
}
In this problem, myatoi works fine and the decimal2binary algorithm is correct, but every time I run the code it gives my output as 0. I do not know why. Is it a problem with pointers? I already set the address of variable data but the output still doesn't change.
./dec2bin "-d" "23" "-b"
The line:
long int fractionfactor = .1;
will set fractionfactor to 0 because the variable is defined as an integer. Try using a float or double instead.
Similarly,
long int dec = myatoi(decimal);
stores an integer value, so wholenum is unnecessary.
Instead of
i = (i << 3) + (i<<1) + (*string -'0');
the code will be much more readable as
i = i * 10 + (*string - '0');
and, with today's optimizing compilers, both versions will likely generate the same object code. In general, especially when your code isn't working, favor readability over optimization.
fraction *= 2; // times by two first
Comments like this, that simply translate code to English, are unnecessary unless you're using the language in an unusual way. You can assume the reader is familiar with the language; it's far more helpful to explain your reasoning instead.
Another coding tip: instead of writing
if (strcmp(argv[1], "-d")) {
if (strcmp(argv[3], "-b")) {
decimal2binary(argv[2], &datai);
printf("output is : %d" , datai);
} else {
printf("invalid parameter");
}
} else {
printf("invalid parameter");
}
you can refactor the nested if blocks to make them simpler and easier to understand. In general it's a good idea to check for error conditions early, to separate the error-checking from the core processing, and to explain errors as specifically as possible so the user will know how to correct them.
If you do this, it may also be easier to realize that both of the original conditions should be negated:
if (strcmp(argv[1], "-d") != 0) {
printf("Error: first parameter must be -d\n");
else if (strcmp(argv[3], "-b") != 0) {
printf("Error: third parameter must be -b\n");
} else {
decimal2binary(argv[2], &datai);
printf("Output is: %d\n" , datai);
}
void decimal2binary(char *decimal, int *binary) {
decimal = malloc(sizeof(char) * 32);
...
}
The above lines of code allocate a new block of memory to decimal, which will then no longer point to the input data. Then the line
long int dec = myatoi(decimal);
assigns the (random values in the) newly-allocated memory to dec.
So remove the line
decimal = malloc(sizeof(char) * 32);
and you will get the correct answer.
if(!strcmp(argv[3] , "-b"))
if(!strcmp(argv[3] , "-d"))
The result of the string compare function should be negated so that you can proceed. Else it will print invalid parameter. Because the strcmp returns '0' when the string is equal.
In the 'decimal2binary' function you are allocating a new memory block inside the function for the input parameter 'decimal',
decimal = malloc(sizeof(char) * 32);
This would actually overwrite your input parameter data.

how to modify detab to accept list of arguments

#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#define TAB_STOP 8
/* replaces tabs from input with the proper amount of blank spots */
int Detab()
{
int c, x;
int column;
x = column = 0;
while((c=getchar())!=EOF)
{
if(c == '\n') /* reseting counter if newline */
{
putchar(c);
return 1;
}
else if(c!='\t') /* column counts places to tab spot */
{
putchar(c);
column++;
if(column == TAB_STOP)
column = 0;
}
else /* tab */
{
for(x=0; x<TAB_STOP - column; x++)
putchar('_');
column = 0;
}
}
return 0;
}
#define MAX_ARGUMENTS 100
int main(int argc, char *argv[])
{
int i, val = 0;
int nums[MAX_ARGUMENTS];
int x = 0;
for(i = 1; i < argc; i++) {
while(isdigit(*argv[i])) {
val = val * 10 + *argv[i] - '0';
*++argv[i];
}
if(x > MAX_ARGUMENTS - 1)
return 0;
nums[x++] = val;
nums[x] = '\0';
val = 0;
}
while(Detab(nums));
printf("Press any key to continue.\n");
getchar();
return 0;
}
In main i put all the arguments(numbers) inside nums array and then pass it to detab. So now im interested what would be the smart way to edit detab so it works. I'm still trying to figure out for a working pseudocode but i dont really know.
The way i tought it should work is:
if arguments are 5, 8, 10 then a tab inside first 4 characters leads to position 5, in 5 - 7th char leads to pos 8 etc.
In case of a newline, the arguments start all over again from the begining.
The most common way is to have Detab accept a pointer (which points to an element in an array) and the length of that array:
int Detab(int* data, int len); // access data[0] through data[len - 1]
Call it like so:
void example() {
int array[] = {5, 8, 10};
Detab(array, 3);
// or:
Detab(array, sizeof array / sizeof *array); // second parameter evaluates to 3
// without using a magic constant
}
Here's some pseudocode for expanding tabs:
def expandtabs_in_line(line, tabstops, default, space):
result = ""
for c in line:
if c != "\t":
result += c
else:
for stop in tabstops:
if stop > len(result):
result += space * (stop - len(result))
break
else:
result += space * (default - (len(result) % default))
return result
def expandtabs(lines, tabstops=[], default=8):
for line in lines:
yield expandtabs_in_line(line, tabstops, default, " ")
Try it out at codepad.

Resources