Related
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;
}
Right now I am trying to convert an int to a char in C programming. After doing research, I found that I should be able to do it like this:
int value = 10;
char result = (char) value;
What I would like is for this to return 'A' (and for 0-9 to return '0'-'9') but this returns a new line character I think.
My whole function looks like this:
char int2char (int radix, int value) {
if (value < 0 || value >= radix) {
return '?';
}
char result = (char) value;
return result;
}
to convert int to char you do not have to do anything
char x;
int y;
/* do something */
x = y;
only one int to char value as the printable (usually ASCII) digit like in your example:
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int inttochar(int val, int base)
{
return digits[val % base];
}
if you want to convert to the string (char *) then you need to use any of the stansdard functions like sprintf, itoa, ltoa, utoa, ultoa .... or write one yourself:
char *reverse(char *str);
const char digits[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
char *convert(int number, char *buff, int base)
{
char *result = (buff == NULL || base > strlen(digits) || base < 2) ? NULL : buff;
char sign = 0;
if (number < 0)
{
sign = '-';
}
if (result != NULL)
{
do
{
*buff++ = digits[abs(number % (base ))];
number /= base;
} while (number);
if(sign) *buff++ = sign;
if (!*result) *buff++ = '0';
*buff = 0;
reverse(result);
}
return result;
}
A portable way of doing this would be to define a
const char* foo = "0123456789ABC...";
where ... are the rest of the characters that you want to consider.
Then and foo[value] will evaluate to a particular char. For example foo[0] will be '0', and foo[10] will be 'A'.
If you assume a particular encoding (such as the common but by no means ubiquitous ASCII) then your code is not strictly portable.
Characters use an encoding (typically ASCII) to map numbers to a particular character. The codes for the characters '0' to '9' are consecutive, so for values less than 10 you add the value to the character constant '0'. For values 10 or more, you add the value minus 10 to the character constant 'A':
char result;
if (value >= 10) {
result = 'A' + value - 10;
} else {
result = '0' + value;
}
Converting Int to Char
I take it that OP wants more that just a 1 digit conversion as radix was supplied.
To convert an int into a string, (not just 1 char) there is the sprintf(buf, "%d", value) approach.
To do so to any radix, string management becomes an issue as well as dealing the corner case of INT_MIN
The following C99 solution returns a char* whose lifetime is valid to the end of the block. It does so by providing a compound literal via the macro.
#include <stdio.h>
#include <stdlib.h>
#include <limits.h>
// Maximum buffer size needed
#define ITOA_BASE_N (sizeof(unsigned)*CHAR_BIT + 2)
char *itoa_base(char *s, int x, int base) {
s += ITOA_BASE_N - 1;
*s = '\0';
if (base >= 2 && base <= 36) {
int x0 = x;
do {
*(--s) = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ"[abs(x % base)];
x /= base;
} while (x);
if (x0 < 0) {
*(--s) = '-';
}
}
return s;
}
#define TO_BASE(x,b) itoa_base((char [ITOA_BASE_N]){0} , (x), (b))
Sample usage and tests
void test(int x) {
printf("base10:% 11d base2:%35s base36:%7s ", x, TO_BASE(x, 2), TO_BASE(x, 36));
printf("%ld\n", strtol(TO_BASE(x, 36), NULL, 36));
}
int main(void) {
test(0);
test(-1);
test(42);
test(INT_MAX);
test(-INT_MAX);
test(INT_MIN);
}
Output
base10: 0 base2: 0 base36: 0 0
base10: -1 base2: -1 base36: -1 -1
base10: 42 base2: 101010 base36: 16 42
base10: 2147483647 base2: 1111111111111111111111111111111 base36: ZIK0ZJ 2147483647
base10:-2147483647 base2: -1111111111111111111111111111111 base36:-ZIK0ZJ -2147483647
base10:-2147483648 base2: -10000000000000000000000000000000 base36:-ZIK0ZK -2147483648
Ref How to use compound literals to fprintf() multiple formatted numbers with arbitrary bases?
Check out the ascii table
The values stored in a char are interpreted as the characters corresponding to that table. The value of 10 is a newline
So characters in C are based on ASCII (or UTF-8 which is backwards-compatible with ascii codes). This means that under the hood, "A" is actually the number "65" (except in binary rather than decimal). All a "char" is in C is an integer with enough bytes to represent every ASCII character. If you want to convert an int to a char, you'll need to instruct the computer to interpret the bytes of an int as ASCII values - and it's been a while since I've done C, but I believe the compiler will complain since char holds fewer bytes than int. This means we need a function, as you've written. Thus,
if(value < 10) return '0'+value;
return 'A'+value-10;
will be what you want to return from your function. Keep your bounds checks with "radix" as you've done, imho that is good practice in C.
1. Converting int to char by type casting
Source File charConvertByCasting.c
#include <stdio.h>
int main(){
int i = 66; // ~~Type Casting Syntax~~
printf("%c", (char) i); // (type_name) expression
return 0;
}
Executable charConvertByCasting.exe command line output:
C:\Users\boqsc\Desktop\tcc>tcc -run charconvert.c
B
Additional resources:
https://www.tutorialspoint.com/cprogramming/c_type_casting.htm
https://www.tutorialspoint.com/cprogramming/c_data_types.htm
2. Convert int to char by assignment
Source File charConvertByAssignment.c
#include <stdio.h>
int main(){
int i = 66;
char c = i;
printf("%c", c);
return 0;
}
Executable charConvertByAssignment.exe command line output:
C:\Users\boqsc\Desktop\tcc>tcc -run charconvert.c
B
You can do
char a;
a = '0' + 5;
You will get character representation of that number.
Borrowing the idea from the existing answers, i.e. making use of array index.
Here is a "just works" simple demo for "integer to char[]" conversion in base 10, without any of <stdio.h>'s printf family interfaces.
Test:
$ cc -o testint2str testint2str.c && ./testint2str
Result: 234789
Code:
#include <stdio.h>
#include <string.h>
static char digits[] = "0123456789";
void int2str (char *buf, size_t sz, int num);
/*
Test:
cc -o testint2str testint2str.c && ./testint2str
*/
int
main ()
{
int num = 234789;
char buf[1024] = { 0 };
int2str (buf, sizeof buf, num);
printf ("Result: %s\n", buf);
}
void
int2str (char *buf, size_t sz, int num)
{
/*
Convert integer type to char*, in base-10 form.
*/
char *bufp = buf;
int i = 0;
// NOTE-1
void __reverse (char *__buf, int __start, int __end)
{
char __bufclone[__end - __start];
int i = 0;
int __nchars = sizeof __bufclone;
for (i = 0; i < __nchars; i++)
{
__bufclone[i] = __buf[__end - 1 - i];
}
memmove (__buf, __bufclone, __nchars);
}
while (num > 0)
{
bufp[i++] = digits[num % 10]; // NOTE-2
num /= 10;
}
__reverse (buf, 0, i);
// NOTE-3
bufp[i] = '\0';
}
// NOTE-1:
// "Nested function" is GNU's C Extension. Put it outside if not
// compiled by GCC.
// NOTE-2:
// 10 can be replaced by any radix, like 16 for hexidecimal outputs.
//
// NOTE-3:
// Make sure inserting trailing "null-terminator" after all things
// done.
NOTE-1:
"Nested function" is GNU's C Extension. Put it outside if not
compiled by GCC.
NOTE-2:
10 can be replaced by any radix, like 16 for hexidecimal outputs.
NOTE-3:
Make sure inserting trailing "null-terminator" after all things
done.
A simple problem but I can't get documentation about this kind of format: I want to print a float in a Fortran scientific notation, with its integer part always being zero.
printf("%0.5E",data); // Gives 2.74600E+02
I want to print it like this:
.27460E+03
How can I get this result as clean as possible?
If you only care about the integer part being 0 and not really leaving out the 0, i.e. if you're fine with 0.27460E+03 instead of .27460E+03 you could do something similar to this:
#include <stdio.h>
#include <stdlib.h>
void fortran_printf();
int main(void)
{
double num = 274.600;
fortran_printf(num);
exit(EXIT_SUCCESS);
}
void fortran_printf(double num)
{
int num_e = 0;
while (num > 1.0) {
num /= 10;
num_e++;
}
printf("%.5fE+%02d", num, num_e);
}
Otherwise you have to take a detour over strings. Note that the code above is only meant to get you started. It certainly doesn't handle any involved cases.
I tried doing this with log10() and pow(), but ended up having problems with rounding errors. So as commented by #Karoly Horvath, string manipulation is probably the best approach.
#include <stdlib.h>
char *fortran_sprintf_double(double x, int ndigits) {
char format[30], *p;
static char output[30];
/* Create format string (constrain number of digits to range 1–15) */
if (ndigits > 15) ndigits = 15;
if (ndigits < 1) ndigits = 1;
sprintf(format, "%%#.%dE", ndigits-1);
/* Convert number to exponential format (multiply by 10) */
sprintf(output, format, x * 10.0);
/* Move the decimal point one place to the left (divide by 10) */
for (p=output+1; *p; p++) {
if (*p=='.') {
*p = p[-1];
p[-1] = '.';
break;
}
}
return output;
}
A string manipulation approach:
int printf_NoIntegerPart(double x, int prec) {
char buf[20 + prec];
sprintf(buf, "%+.*E", prec - 1, x * 10.0); // use + for consistent width output
if (buf[2] == '.') {
buf[2] = buf[1];
buf[1] = '.';
}
puts(buf);
}
int main(void) {
printf_NoIntegerPart(2.74600E+02, 5); // --> +.27460E+03
}
This will print "INF" for |x| > DBL_MAX/10
printf() will not meet OP’s goal in one step using some special format. Using sprintf() to form the initial textual result is a good first step, care must be exercised when trying to do “math” with string manipulation.
Akin to #user3121023 deleted answer.
#include <assert.h>
#include <stdlib.h>
#include <stdio.h>
int printf_NoIntegerPart(double x, int prec) {
assert(prec >= 2 && prec <= 100);
char buffer[prec + 16]; // Form a large enough buffer.
sprintf(buffer, "%.*E", prec - 1, x);
int dp = '.'; // Could expand code here to get current local's decimal point.
char *dp_ptr = strchr(buffer, dp);
char *E_ptr = strchr(buffer, 'E');
// Insure we are not dealing with infinity, Nan, just the expected format.
if (dp_ptr && dp_ptr > buffer && E_ptr) {
// Swap dp and leading digit
dp_ptr[0] = dp_ptr[-1];
dp_ptr[-1] = dp;
// If x was not zero …
if (x != 0) {
int expo = atoi(&E_ptr[1]); // Could use `strtol()`
sprintf(&E_ptr[1], "%+.02d", expo + 1);
}
}
return puts(buffer);
}
int main(void) {
printf_NoIntegerPart(2.74600E+02, 5); // ".27460E+03"
return 0;
}
Faced same issue while fortran porting.
DId not found std C format :(
Implemented both approaches - with log10/pow and with string manipulation.
#include <ansi_c.h>
#define BUFFL 16
// using log10 , 3 digits after "."
char* fformat1(char* b, double a) {
int sign = 1;
double mant;
double order;
int ord_p1;
if (a<0) {
sign =-1;
a = -a;
}
order=log10 (a);
if (order >=0) ord_p1 = (int) order +1; // due sto property of int
else ord_p1 = (int) order;
mant=a/(pow(10,ord_p1));
sprintf(b,"%.3fE%+03d",mant,ord_p1);
if (sign==-1) b[0]='-';
return b;
}
// using string manipulation
char* fformat2(char* b, double a) {;
int sign = 1;
int i;
int N=3;
if (a<0) {
sign =-1;
a = -a;
}
sprintf(b,"%0.3E",a*10); // remember - we *10 to have right exponent
b[1]=b[0]; // 3.123 => .3123
b[0]='.';
for (i=N; i>=0; i--) // and shif all left
b[i+1]=b[i];
b[0]='0'; // pad with zero 0.312
if (sign==-1) b[0]='-'; // sign if needed
return b;
}
int main () {
char b1[BUFFL]; // allocate buffer outside.
char b2[BUFFL];
char b3[BUFFL];
char b4[BUFFL];
char b5[BUFFL];
printf("%s %s %s %s %s \n", fformat(b1,3.1), fformat(b2,-3.0), fformat(b3,3300.),
fformat(b4,0.03), fformat(b5,-0.000221));
printf("%s %s %s %s %s \n", fformat2(b1,3.1), fformat2(b2,-3.0), fformat2(b3,3300.),
fformat2(b4,0.03), fformat2(b5,-0.000221));
return 1;
}
I am using sprintf for string formation in C.
I need to insert '+' and '-' sign before float value.
This positive and negative signs are inserted by checking a flag after that i insert the float value.
Now i want to make this whole number in right alignment along with positive or negative sign.
Currently this is my formatted string:
+300.00
-200.00
+34.60
I want output like following,
+300.00
+233.45
-20.34
I have written following code:
char printbuff[1000], flag = 1;
double temp=23.34, temp1= 340.45;
sprintf(printBuff, "%c%-lf\n%c%-lf",
(Flag == 1) ? '+' : '-',
temp,
(Flag == 1) ? '+' :'-',
temp1);
I am getting following output:
+23.34
+340.45
Instead of the desired:
+23.45
+340.45
How can I do this?
use like this
sprintf(outputstr, "%+7.2f", double_number);
E.g.
#include <stdio.h>
#include <string.h>
#include <math.h>
void output_string(char output_buffer[], double nums[], size_t size){
/* use '+' flag version
int i,len=0;
for(i=0;i<size;++i)
len += sprintf(output_buffer + len, "%+7.2f\n", nums[i]);
*/ //handmade version
int i, len=0;
for(i=0;i<size;++i){
char sign = nums[i] < 0 ? '-' : '+';
char *signp;
double temp = abs(nums[i]);
len += sprintf(signp = output_buffer + len, "%7.2f\n", temp);
signp[strcspn(signp, "0123456789")-1] = sign;//The width including the sign is secured
}
}
int main(){
double nums[] = {
+300.00,
-200.00,
+34.60,
+300.00,
+233.45,
-20.34
};
char output_buffer[1024];
int size = sizeof(nums)/sizeof(*nums);
output_string(output_buffer, nums, size);
printf("%s", output_buffer);
return 0;
}
int main()
{
char s[100];
double x=-100.00;
sprintf(s,"%s%f",x<0?"":"+",x);
printf("\n%s",s);
x = 1000.01;
sprintf(s,"%s%f",x<0?"":"+",x);
printf("\n%s",s);
return 0;
}
Here is the code.
Its O/p is ::
-100.000000
+1000.010000
you need a separate buffer, in which you sprintf your number with your sign, and that resulting string you can sprintf into the rightjustified resultbuffer.
You need something like:
char str[1000];
double v = 3.1415926;
sprintf(str, "%+6.2f", v);
The + indicates "show sign".
A more complete bit of code:
#include <stdio.h>
int main()
{
double a[] = { 0, 3.1415, 333.7, -312.2, 87.8712121, -1000.0 };
int i;
for(i = 0; i < sizeof(a)/sizeof(a[0]); i++)
{
printf("%+8.2f\n", a[i]);
}
return 0;
}
Output:
+0.00
+3.14
+333.70
-312.20
+87.87
-1000.00
Obviously, using sprintf, there would be a buffer involved, but I believe this shows the solution more easily.
This is the sample code of my program, in which i've to add two string type integer (ex: "23568" and "23674"). So, i was trying with single char addition.
char first ='2';
char second ='1';
i was trying like this..
i=((int)first)+((int)second);
printf("%d",i);
and i'm getting output 99, because, it's adding the ASCII value of both. Anyone please suggest me, what should be the approach to add the char type number in C.
Since your example has two single chars being added together, you can be confident knowing two things
The total will never be more than 18.
You can avoid any conversions via library calls entirely. The standard requires that '0' through '9' be sequential (in fact it is the only character sequence that is mandated by the standard).
Therefore;
char a = '2';
char b = '3';
int i = (int)(a-'0') + (int)(b-'0');
will always work. Even in EBCDIC (and if you don't know what that is, consider yourself lucky).
If your intention is to actually add two numbers of multiple digits each currently in string form ("12345", "54321") then strtol() is your best alternative.
i=(first-'0')+(second-'0');
No need for casting char to int.
if you want to add the number reprensations of the characters, I would use "(first - '0') + (second - '0');"
The question seemed interesting, I though it would be easier than it is, adding "String numbers" is a little bit tricky (even more with the ugly approach I used).
This code will add two strings of any length, they doesn't need to be of the same length as the adding begins from the back. Your provide both strings, a buffer of enough length and you ensure the strings only contains digits:
#include <stdio.h>
#include <string.h>
char * add_string_numbers(char * first, char * second, char * dest, int dest_len)
{
char * res = dest + dest_len - 1;
*res = 0;
if ( ! *first && ! *second )
{
puts("Those numbers are less than nothing");
return 0;
}
int first_len = strlen(first);
int second_len = strlen(second);
if ( ((first_len+2) > dest_len) || ((second_len+2) > dest_len) )
{
puts("Possibly not enough space on destination buffer");
return 0;
}
char *first_back = first+first_len;
char *second_back = second+second_len;
char sum;
char carry = 0;
while ( (first_back > first) || (second_back > second) )
{
sum = ((first_back > first) ? *(--first_back) : '0')
+ ((second_back > second) ? *(--second_back) : '0')
+ carry - '0';
carry = sum > '9';
if ( carry )
{
sum -= 10;
}
if ( sum > '9' )
{
sum = '0';
carry = 1;
}
*(--res) = sum;
}
if ( carry )
{
*(--res) = '1';
}
return res;
}
int main(int argc, char** argv)
{
char * a = "555555555555555555555555555555555555555555555555555555555555555";
char * b = "9999999999999666666666666666666666666666666666666666666666666666666666666666";
char r[100] = {0};
char * res = add_string_numbers(a,b,r,sizeof(r));
printf("%s + %s = %s", a, b, res);
return (0);
}
Well... you are already adding char types, as you noted that's 4910 and 5010 which should give you 9910
If you're asking how to add the reperserented value of two characters i.e. '1' + '2' == 3 you can subtract the base '0':
printf("%d",('2'-'0') + ('1'-'0'));
This gives 3 as an int because:
'0' = ASCII 48<sub>10</sub>
'1' = ASCII 49<sub>10</sub>
'2' = ASCII 50<sub>10</sub>
So you're doing:
printf("%d",(50-48) + (49-48));
If you want to do a longer number, you can use atoi(), but you have to use strings at that point:
int * first = "123";
int * second = "100";
printf("%d", atoi(first) + atoi(second));
>> 223
In fact, you don't need to even type cast the chars for doing this with a single char:
#include <stdlib.h>
#include <stdio.h>
int main(int argc, char* argv[]) {
char f1 = '9';
char f2 = '7';
int v = (f1 - '0') - (f2 - '0');
printf("%d\n", v);
return 0;
}
Will print 2
But beware, it won't work for hexadecimal chars
This will add the corresponding characters of any two given number strings using the ASCII codes.
Given two number strings 'a' and 'b', we can compute the sum of a and b using their ASCII values without type casting or trying to convert them to int data type before addition.
Let
char *a = "13784", *b = "94325";
int max_len, carry = 0, i, j; /*( Note: max_len is the length of the longest string)*/
char sum, *result;
Adding corresponding digits in a and b.
sum = a[i] + (b[i] - 48) + carry; /*(Because 0 starts from 48 in ASCII) */
if (sum >= 57)
result[max_len - j] = sum - 10;
carry = 1;
else
result[max_len - j] = sum;
carry = 0;
/* where (0 < i <= max_len and 0 <= j <= max_len) */
NOTE:
The above solution only takes account of single character addition starting from the right and moving leftward.
if you want to scan number by number, simple atoi function will do it
you can use
atoi() function
#include <stdio.h>
#include <stdlib.h>
void main(){
char f[] = {"1"};
char s[] = {"2"};
int i, k;
i = atoi(f);
k = atoi(s);
printf("%d", i + k);
getchar();
}
Hope I answered you question