C Program To Calculate Numbers Squared | Arguments Segmentation Fault - c

I'm a beginner to C, trying to write a program to calculate a square number. At my college we're not allowed to use printf() or scanf() which makes things a bit complicated.
This led me to using arguments to get input. I'm getting a segmentation fault (core dumped) when I try to compile. I think this comes from using argv and indexes but I'm not sure how to fix it.
Do you have some insight that might help? It would be much appreciated!
#include <unistd.h>
int main(int argc, char *argv[]) {
int number;
int square;
while(argc != 0) {
number = argv[1][square];
square = number * number;
write(1, &square, 1);
square++;
}
write(1, "\n", 1);
return 0;
}

The segmentation fault, if not caused by something else first will be caused here:
number = argv[1][square];//seg fault possible when square becomes
//larger than strlen(argv[1]) + 1
Attempting to access memory that the program process does not own, as above, will invoke undefined behavior.
Also, at the time this expression is executed:
square = number * number;
it is unknown what value was contained in square.
These two values should be initialized:
int number = 0;
int square = 0;//this specifically will cause problems later if not initialized
Also, at the time this is called:
number = argv[1][square];
argv[1] is a string, and needs to be converted to an integer before using.
number = atoi(argv[1]);
Next, the statement:
number = argv[1][square]; //seg fault possible as noted above.
will blow up when the value of square becomes larger than then string length of argv[1].
If your intent is squaring the value contained in argv[1] in its entirety as a single numeric value, it must first be converted from a string array, to an integer value, then you can easily get the square as you do in your code:
int number = atoi(argv[1]);
square = number * number;
If, as it appears in your code, you are interested in squaring each of the component integers making up the string, then given the input of "1234, to convert each of the digits inargv1from ASCII value to its numeric value. (i.e.val = argv1[x] - '0'==>x`), then square it, then move the the next character in the array and so on.... look at the other part of this answer below.
The following is an adaptation of your original to do this...
int main(int argc, char *argv[]) {
int number = 0;
int square = 0;
if(argc != 2)
{
printf("%s\n","Usage prog.exe <nnn>, where nnn is an integer value.\nProgram will exit.");
}
else
{
char *ptr = argv[1];
while(*ptr != '\0')
{
number = *ptr - '0';
square = number * number;
printf("%d\n", square);//write() not available on my system, replace as necessary
square++;
ptr++;
}
}
return 0;
}
So, for example given prog.exe "1234", the output is:

The completed code should look like this :
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char **argv) {
int number;
int square;
if(argc == 2) {
number = atoi(argv[1]);
square = number * number;
char sq_buffer[12];
sprintf(sq_buffer , "%d" , square);
strcat(sq_buffer , "\n");
write(1, (const void *) sq_buffer, strlen(sq_buffer));
}else{
char message[100];
strcpy(message , "Please specify exactly one argument \n");
write(1 , (const void *)message , strlen(message));
}
return 0;
}

When you say that you are not allowed to use 'printf', does that also include 'fprintf' and 'sprintf'? If so, then I would solve this problem like this:
void main( int argc, char **argv )
{
int i;
int j;
int square;
int value;
char buffer[256];
for (i = 1; i < argc; i++) {
/* Get the next integer from the args to the program */
value = atoi(argv[i]);
/* Calculate the square of that value */
square = value * value;
/* Now convert it to ASCII */
itoa(square, buffer, 10);
/* Write out the data */
write(1, buffer, strlen(buffer));
/* You could also use putchar() for it, like this: */
j = 0;
while (buffer[j] != '\0')
putchar(buffer[j++]);
}
}
If he doesn't want you using itoa(), then you could write your own int to ASCII conversion routine like this:
char *IntToASCII( int x )
{
static char buffer[256];
char *ptr;
int neg;
char *digits = "0123456789";
unsigned long tempX;
neg = (x < 0);
tempX = x;
if (neg) {
tempX *= -1;
}
ptr = buffer + sizeof(buffer) - 1;
*ptr = '\0';
do {
ptr--;
*ptr = digits[tempX % 10];
tempX /= 10;
} while (tempX > 0);
if (neg)
*ptr = '-';
return (ptr);
}
Or you can make 'buffer' an input parameter and remove the static declaration for it.

#define STDOUT_FILENO 1
#define MAX_INT_DIGITS (10+1) /*+1 for string null terminating*/
int main(int argc, char *argv[])
{
int number=0, square=0;
char ret_num[MAX_INT_DIGITS];
for (int i =1; i < argc; ++i)
{
number = atoi(argv[i])
square = number * number;
itoa(square, ret_num, 10);
write(STDOUT_FILENO, ret_num, strlen(ret_num));
/*write new line*/
write(STDOUT_FILENO, '\n', 1);
}
return 0;
}

Related

Factorial program displaying the inital value and not the factorial itself

Below is my program to calculate the factorial of a given int. It compiles but only displays the initial value of the fact. It most likely has something to do with the if(argc>1) statement, but that is required for the assignment.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char* aragv[])
{
int fact = 1;
int n = atoi(char* aragv[]);
if(argc>1)
{
for(int i = 1; i < n ; i++)
{
n = n * i;
}
}
printf("%d\n", fact);
return 0;
}
Heavily commented code :
#include <stdio.h>
#include <stdlib.h>
#define USAGE "USAGE: ./program [+ve number upto 20]" // define constants & repetitive texts
int main(int argc, char* argv[]) // argc & argv have universal appeal
{
//int fact = 7; // use larger integer
unsigned long int factorial = 1; // 0! = 1
//if(argc>1) // instead check program is run with an argument
if (argc != 2) { // invalid program run
printf ("\n\t%s\n", USAGE);
return 1; // return non-zero to indicate error to caller
}
int number ; //= atoi (argv[1]); // convert string to integer; number is in argv[1]
// #DavidC.Rankin correction
if (sscanf (argv[1], "%d", &number) != 1) { // to make sure we read "a number"
printf ("\n\tERROR: Invalid Number [%s]\n\t%s\n", argv[1], USAGE);
return 3;
}
if (number > 20 || number < 0) { // long int (64 bits) can't store more than 20!
printf ("\n\tERROR: [%d] Out of valid range [0 to 20]\n\t%s\n", number, USAGE);
return 2; // different number for different scenarios
}
for (int i = 2; i <= number; i++) // you can skip 1 as doesn't make a difference
factorial = factorial * i;
printf("\nAnswer:\t %d! = %lu\n", number, factorial); // %lu for unsigned long int
return 0;
}
When you're learning, it always helps if you learn in increments.

Reverse a character array without changing value of number?

I have for example a string (mathematical equation in postfix notation) that looks like this: The numbers are 5.33,5.32,6.33,3.22
5.335.32*6.333.22++
I'm looking to make it into prefix notation but simply reversing the string won't work due to the fact it has to retain the value of the number.
I've thought of doing a normal character by character swap in a for loop, and when encountering a digit make that into a substring and place it on afterwards but I haven't gotten it to work properly and now I'm stuck.
My end-goal is to make a binary expression tree out of that, so if there's an easier way than doing this also please let me know.
A stack-based approach:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *postfix_to_prefix(const char *string) {
char operator, *stack[1024];
int s = 0, number, fraction;
const char *tokens = string;
while (1) {
if (sscanf(tokens, "%1d.%2d", &number, &fraction) == 2) {
stack[s] = malloc(sizeof("1.00"));
(void) sprintf(stack[s++], "%4.2f", number + (fraction / 100.0));
tokens += strlen("1.00");
} else if (sscanf(tokens, "%c", &operator) == 1) {
char *operand1 = stack[--s];
char *operand2 = stack[--s];
stack[s] = malloc(strlen(operand1) + strlen(operand1) + sizeof(operator) + sizeof('\0'));
(void) sprintf(stack[s++], "%c%s%s", operator, operand1, operand2);
free(operand1);
free(operand2);
tokens += sizeof(operator);
} else {
break;
}
}
return stack[--s];
}
int main() {
const char *string = "5.335.32*6.333.22++";
printf("%s\n", string);
char *inverted = postfix_to_prefix(string);
printf("%s\n", inverted);
free(inverted);
return 0;
}
OUTPUT
> ./a.out
5.335.32*6.333.22++
++3.226.33*5.325.33
>
This is a bare bones implementation with no real error checking nor other finishing touches. You'll want to check that non-communitive operations like subtraction and division come out with the operands in the correct order and reverse them if not.
#include <stdio.h>
#include <string.h>
#include <ctype.h>
int main(void) {
char exp[] = "5.335.32*6.333.22++";
size_t len = strlen(exp);
char temp[len];
char *p = temp;
for(int i = len-1; i >= 0; ){
if(isdigit(exp[i])){
memcpy(p, &exp[i-4+1], 4);//all number have a length of 4
p += 4;
i -= 4;
} else {
*p++ = exp[i--];//length of op is 1
}
}
memcpy(exp, temp, len);//Write back
puts(exp);//++3.226.33*5.325.33
return 0;
}

convert int to string with decimals

I want to write my own function in C for various reasons that converts an int to a string of decimals, just like sprintf.
Example:
int number = 254;
char string[10];
sprintf(string, "%d", number);
The string should look like this after the function I want to write:
[0] 2
[1] 5
[2] 4
[3] '\0'
Just to clarify even further, I want to program the actual convertion of an int to a string of chars. I don't want to use sprintf or itoa etc to do it. I want to know how it is done and be able to program it myself and do small adjustments to it.
Additional clarification:
I don't want to use itoa or sprintf, but pretty much program these myself.
#include <stdio.h>
#include <stdlib.h>
int i2a(char *s, int n){
div_t qr;
int pos;
if(n == 0) return 0;
qr = div(n, 10);
pos = i2a(s, qr.quot);
s[pos] = qr.rem + '0';
return pos + 1;
}
char* my_itoa(char *output_buff, int num){
char *p = output_buff;
if(num < 0){
*p++ = '-';
num *= -1;
} else if(num == 0)
*p++ = '0';
p[i2a(p, num)]='\0';
return output_buff;
}
int main(void){
int number = -254;
char string[12];
printf("%s", my_itoa(string, number));
return 0;
}
int number = 254;
int back=0,i=0;
char ch='\0';
char string[10];
for(i=0;(number/10)==0;i++){
back=number%10;
ch=(back*pow(10,i)+48);
string[i]=ch;
}
divide number per 10
get the rest( with % ) the rest is the digit you want starting from the right
cast the digit to char +48(ascii 0)
add to string

Trying to put some digits into a char array

I'm trying to create a char array made of some letters and numbers (the function was way more complex initially but i kept simplifying it to figure out why it doesn't work properly). So i have a char array in which i put 2 chars, and try to add some numbers to it.
For a reason i can't figure out, the numbers do not get added to the array. It might be really stupid but I'm new to C so here's the simplified code. Any help is much appreciated, thanks!
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char some_string[20];
char *make_str() {
some_string[0] = 'a';
some_string[1] = 'x';
int random = 0;
int rand_copy = 0;
random = (rand());
rand_copy = random;
int count = 2;
while ( rand_copy > 0 ) {
rand_copy = rand_copy / 10;
++count;
}
int i=2;
for (i=2; i<count; i++) {
some_string[i] = random%10;
random = random/10;
}
return (some_string);
}
int main(int argc, const char *argv[]) {
printf("the string is: %s\n",make_str());
return 0;
}
You have many problems:
resulting string is not zero-terminated. Add some_string[i] = '\0'; to fix this
character (char) is something like "a letter", but random % 10 produces a number (int) which when converted to character results in control code (ASCII characters 0-9 are control codes). You'd better use some_string[i] = (random % 10) + '0';
you're using fixed length string (20 characters), which may be enough, but it could lead to many problems. If you are a beginner and haven't learn dynamic memory allocation, than that's ok for now. But remember that fixed-length buffers are one of top-10 reasons for buggy C-code. And if you have to use fixed-length buffers (there are legitimate reason for doing this), ALLWAYS check if you are not overrunning the buffer. Use predefined constants for buffer length.
unless the whole point of your excercise is to try converting numbers to strings, use libc function like snprintf for printing anything into a string.
don't use global variable (some_string) and if you do (it's ok for a small example), there is no point in returning this value.
Slightly better version:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define BUF_LENGTH 20
char some_string[BUF_LENGTH];
char *make_str() {
some_string[0] = 'a';
some_string[1] = 'x';
int random = rand();
int rand_copy = random;
int count = 2;
while (rand_copy > 0) {
rand_copy = rand_copy / 10;
++count;
}
int i;
for (i = 2; i < count; i++) {
/* check for buffer overflow. -1 is for terminating zero */
if (i >= BUF_LENGTH - 1) {
printf("error\n");
exit(EXIT_FAILURE);
}
some_string[i] = (random % 10) + '0';
random = random / 10;
}
/* zero-terminate the string */
some_string[i] = '\0';
return some_string;
}
int main(int argc, const char *argv[]) {
printf("the string is: %s\n",make_str());
return 0;
}

Get to number from an array and assign to one int

I'm working on my homework and trying to get two characters which are numbers from an array for example ABC10DEF
I want to get 10 and store it in an int type.
number_holder_1 = back[3] - '0';
number_holder_2 = back[4] - '0';
number = number_holder_1 * 10 + number_holder_2;
This doesn't work I don't know why.
When I print out the value of number_holder_1 it does display 1 and when I display number_holder_2 it display 0 but when I print number it just display 0
I don't know how.
UPDATE:
The number, number_holder_1 and number_holder_2 are define as int type.
the array called back that holding ABC10DEF is passing from the main.
It appears to be an implementation mistake, because using what you have given, with some better variable names, it does work.
#include <stdio.h>
#include <ctype.h>
int letter2int(char c) {
int n;
if (isdigit(c)) {
n = c - '0';
} else {
n = -1; /* error */
}
/* for debugging */
printf("For character '%c' we get number '%d'.\n", c, n);
return n;
}
int main(int argc, char** argv) {
const char str[] = "ABC10DEF";
int tens, ones;
int result;
tens = letter2int(str[3]);
ones = letter2int(str[4]);
result = tens * 10 + ones;
printf("Result: %d\n", result);
return 0;
}
This can be generalized to either form a atoi function (ASCII to integer) or extract the first number that occurs in a string (terminated by any non-digit character) by using a loop and a char pointer to index over the string str.
Using i as the zero-based index, result += number * (int)pow(10, i);.

Resources