In this code Why Write() doesn't work with Int? - c

I cannot understand why this code doesnt work. it works fine with printf but i cannot get it to work with write...
#include <stdio.h>
#include <unistd.h>
int ft_putchar(char a,char b,char c){
write(1,&a,1);
write(1,&b,1);
write(1,&c,1);
return(0);
}
int main()
{
int x = 0;
int y, z;
while(x <= 9){
y = x + 1;
while(y <= 9){
z = y + 1;
while(z <= 9){
ft_putchar(x,y,z);
z++;
}
y++;
}
x++;
}
return 0;
}
there are no error outputs

You need to convert ASCII to its digit equivalent before writing.
example 5 = '5' +'0'
As of now you are writing the ASCII values to terminal.
int ft_putchar(char a,char b,char c){
a += '0';
b += '0';
c += '0';
write(1,&a,1);
write(1,&b,1);
write(1,&c,1);
return(0);
}
i want to print them like this but in the end it should have nothing
578, 579, 589, 678, 679, 689, 789, instead of 789, it should be 789 im
using c= ','; write(1,&c,1); c= ' '; write(1,&c,1);
You need to pass the delimiter to ft_putchar function,
int ft_putchar(char a,char b,char c, char del){
a += '0';
b += '0';
c += '0';
write(1,&a,1);
write(1,&b,1);
write(1,&c,1);
write(1,&del,1);
return(0);
}
int main()
{
int x = 0;
int y, z;
while(x <= 9){
y = x + 1;
while(y <= 9){
z = y + 1;
while(z <= 9){
if (x == 7 && y == 8 && z == 9)
ft_putchar(x,y,z, ' ');
else
ft_putchar(x,y,z, ',');
z++;
}
y++;
}
x++;
}
return 0;
}

When you used printf, I am guessing you used:
printf("%d %d %d",a,b,c);
So you are explicitly telling the function to interpret the variables as numbers, and print those. When you use write, it assumes that what you are using is a char. This means this would be the same as:
printf("%c %c %c",a,b,c);
Try that - you will see you still get blanks. That is because you are not interpreting the variables as characters, and so converting the numbers 1..9 to their ASCII letter value. These are not normal characters and will appear blank.
This would be the same if you used char in main instead of int. Your best option to convert a normal integer to a the ASCII value that prints said integer is via the answer by Kiran,
myInt += '0'; //Only works for numbers than 0..9. You may has well have used char to save space.
since all ASCII characters for numbers are consecutive.

Related

Can someone explain to me how the modulo character works to output a leading zero

This is the original question:
Create a function that displays all different combination of two digits between 00
and 99, listed by ascending order.
This was how a fellow student did it. It compiles. So all the first single digit outputs have to have a leading zero. I dont understand how he achieved it. Can someone explain to me this a%10 +0 part and how that works to print leading zeros? Thank you in advance.
void ft_print_comb2(void)
{
int x;
int y;
enter code here
x = 0;
while (x < 99)
{
y = x + 1;
while (y < 100)
{
output_format(x, y);
printlines(x, y);
y++;
}
x++;
}
}
void output_format(int x, int y)
{
if (!((x == 99 && y == 99) || (x == 0 && y == 1)))
{
write(1, ", ", 2);
}
}
void printlines(int x, int y)
{
char xmodule;
char xdiv;
char ymodule;
char ydiv;
xmodule = (x % 10 + '0');
xdiv = (x / 10 + '0');
ymodule = (y % 10 + '0');
ydiv = (y / 10 + '0');
write(1, &xdiv, 1);
write(1, &xmodule, 1);
write(1, " ", 1);
write(1, &ydiv, 1);
write(1, &ymodule, 1);
}
For numbers between 0 and 100, x%10 + '0' is the ASCII value of the lowest digit of x, and x/10 + '0' is the ASCII value[1] of the tens digit (or 0 if the number is less than 10). '0' is the ASCII value that represents the character 0, and x%10 is the remainder when dividing x by 10. That's the trick used by your friend's code.
[footnote 1] (or more accurately, the character code from the character set of the execution environment which may or may not be ASCII).
However, the code written is quite complicated, and formatting numbers for output (including leading zeros) is provided by the standard library. Loops that range between two numbers can be conveniently described using a for loop. The function write used by the program is POSIX, and not part of the C standard library.
Here's a complete version using printf:
#include <stdio.h>
int main(int argc, char *argv[]) {
for (int x = 0; x < 100; x++) {
for (int y = x+1; y < 100; y++) {
if (y!=1) printf(", "); // skip comma for the first pair output.
printf("%02d %02d", x, y);
}
}
printf("\n");
return 0;
}

Issues with a Caesar Cipher

So the main issue is that the addition of (-5 to 4) to the characters in the entered string is all messed up to show possible words that were encrypted. When the loop runs the enter characters are not the starting point thus throwing everything else off. Additionally, I cannot get the repeat = false statement to register.
#include<stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <string.h>
int main()
{
char encrypted_string[100];
char z;
char stop[]="STOP";
int x=-5, y, len;
bool repeat = true;
while (repeat)
{
printf("Enter the encrypted word (type STOP to quit) : ");
fgets(encrypted_string, 100, stdin);
if (strcmp(encrypted_string, stop)== 0)
{
repeat = false;
}
//len=strlen(encrypted_string);
while (x < 5)
{
for (y = 0; encrypted_string[y] != '\0'; y++)
{
z = encrypted_string[y];
if (z >= 97 && z <= 122)
{
z=z+x;
if (z < 97)
{
z=z+(122-97)+1;
}
encrypted_string[y] = z;
}
else if (z >= 65 && z <= 90)
{
z=z+x;
if (z < 65)
{
z=z+(90-65)+1;
}
encrypted_string[y] = z;
}
}
printf("For shift of %d, decrypted word is %s\n", x++, encrypted_string);
}
}
return 0;
}
char stop[]="STOP";
fgets(encrypted_string, 100, stdin);
if (strcmp(encrypted_string, stop)== 0)
fgets() leaves the trailing newline in the buffer, so this will never be true if the user hit enter at the end of the line.
if (z >= 97 && z <= 122)
These look a bit like magic numbers, probably better to write 'a' and 'z' instead.
if (z >= 97 && z <= 122) {
z=z+x;
if (z < 97)
What if the increment x is positive? z could go over 122.
Actually, why is it named x? It's the shift offset, so call it that.
Similarly, y is an index, so perhaps i instead. Especially confusing is that you have x, y and z that are three totally different things.
while (x < 5) {
for (y = 0; encrypted_string[y] != '\0'; y++) {
...
encrypted_string[y] = z;
You're modifying the same string you read again on the next iteration. For the input foo, it does a shift of -5 giving ajj, then a shift of -4 from that, giving wff, etc.

Reverse the output of printf function in while loop

I wrote a code for a b-adic representation of a chosen number.
#include <stdio.h>
int b_adisch (int a, int b)
{
int x, y, mod, mod1;
x = a / b;
mod1 = a % b;
printf("%i\n", mod1);
do {
y = x / b;
mod = x % b;
x = y;
printf("%i\n", mod);
} while(x != 0);
return a ;
}
int main (void)
{
int a, b;
printf("pls input a ");
scanf("%i", &a);
printf("pls input b ");
scanf("%i", &b);
b_adisch(a, b);
return 0;
}
The output order will be reversed
since the printf has to be put into the while loop and the calculation starts with the last number of the representation.
Example if a = 10 and b = 2
The output is 0101
but it should be 1010
How can I change my code to make this happen?
How can i change my code to make this happen?
2 approaches:
Compute the digits from least to most significant and save in a adequate sized buffer. This is similar to OP's approach yet saves the results of each digit's computation for later printing.
#include <assert.h>
#include <limits.h>
void b_adisch(int value, int base) {
// Let us work with simple cases first.
assert(value >= 0);
assert(base >= 2 && base <= 10);
// Adequate sized buffer
char buffer[sizeof value * CHAR_BIT + 1];
// Start at end
char *end = &buffer[sizeof buffer - 1];
*end = '\0';
do {
end--;
int digit = value%base; // Find least digit
value /= base;
*end = digit + '0'; // save the digit as text
} while (value);
printf("<%s>\n", end); // print it as a string
}
Use recursion. A more radical change; This computes and prints the output of the more significant digits first.
void b_adischR_helper(int value, int base) {
// If the value is at least 2 digits, print the most significant digits first
if (value >= base) {
b_adischR_helper(value/base, base);
}
putchar(value % base + '0'); // Print 1 digit as text
}
void b_adischR(int value, int base) {
// Let us work with simple cases first.
assert(value >= 0);
assert(base >= 2 && base <= 10);
printf("<");
b_adischR_helper(value, base);
printf(">\n");
}
Test
int main() {
b_adisch(10, 2);
b_adischR(10, 2);
b_adisch(INT_MAX, 10);
b_adischR(INT_MAX, 10);
b_adisch(INT_MAX, 2);
b_adischR(INT_MAX, 2);
}
Output
<1010>
<1010>
<2147483647>
<2147483647>
<1111111111111111111111111111111>
<1111111111111111111111111111111>
You can store the output in an array as here it is stored in "arr" and later print the output in reverse order (from end to start).
#include <stdio.h>
int arr[10000]={0};
void b_adisch (int a, int b)
{
int x, y, mod, mod1,i=0,j;
x = a / b;
mod1 = a % b;
arr[i++]=mod1;
do {
y = x / b;
mod = x % b;
x = y;
arr[i++]=mod;
} while(x != 0);
for(j=i-1;j>=0;j--)
printf("%i\n",arr[j]);
}
int main (void)
{
int a, b;
printf("pls input a ");
scanf("%i", &a);
printf("pls input b ");
scanf("%i", &b);
b_adisch(a, b);
return 0;
}

Removing numbers 8 and 9 from a variable. What am I doing wrong?

I'm trying to input two numbers and remove 8s and 9s (not convert them, only remove unneeded numbers) so they can fit in the octal base.
When I run the program and input the numbers, they are almost correctly returned, but they are deducted by a bit.
I still don't know why and how to fix it. It might be something with zeroes, but I don't know.
int octal(int a)
{
int b = 0;
int i = 0;
while(a > 0){
if((a % 10) <= 7){
b= pow(10,i) * (a%10)+b;
i++;
}
a=a/10;
}
return b;
}
int main()
{
int j, o, a, b;
scanf(" %d %d", &j, &o);
a=octal(j);
b=octal(o);
printf("%d\n%d\n",a,b);
return 0;
}
edit: Example
Input: 72349 and 91238
Output: 7233 and 122
Code is encountering a weak double pow() that is returning values near the expected mathematical result. When the result is just under a whole number, the conversion back to int results in fraction truncation - results appear 1 less then expected.
Could use round(pow(10,i)) or better yet, stay with int math as follows.
Other simplifications possible, but minimal code changes to outline OP's issue.
int octal(int a) {
int b = 0;
int i = 0;
int pow10 = 1;
while (a > 0) {
if ((a % 10) <= 7) {
//b = pow(10,i) * (a%10)+b;
b = pow10 * (a % 10) + b;
pow10 *= 10;
i++;
}
a = a / 10;
}
return b;
}
Care for a walk on the recursive side of life?
int octal(int a) {
assert(a >= 0);
while (a >= 8) {
int digit = a%10;
a /= 10;
if (digit < 8) {
return octal(a)*10 + digit;
}
}
return a;
}

atoi implementation in C

I can't understand the following atoi implementation code, specifically this line:
k = (k << 3) + (k << 1) + (*p) - '0';
Here is the code:
int my_atoi(char *p) {
int k = 0;
while (*p) {
k = (k << 3) + (k << 1) + (*p) - '0';
p++;
}
return k;
}
Can someone explain it to me ?
Another question: what should be the algorithm of atof implementation ?
<< is bit shift, (k<<3)+(k<<1) is k*10, written by someone who thought he was more clever than a compiler (well, he was wrong...)
(*p) - '0' is subtracting the value of character 0 from the character pointed by p, effectively converting the character to a number.
I hope you can figure out the rest... just remember how the decimal system works.
Here is a specification for the standard function atoi. Sorry for not quoting the standard, but this will work just as fine (from: http://www.cplusplus.com/reference/clibrary/cstdlib/atoi/ )
The function first discards as many whitespace characters (as in
isspace) as necessary until the first non-whitespace character is
found. Then, starting from this character, takes an optional initial
plus or minus sign followed by as many base-10 digits as possible, and
interprets them as a numerical value.
The string can contain additional characters after those that form the
integral number, which are ignored and have no effect on the behavior
of this function.
If the first sequence of non-whitespace characters in str is not a
valid integral number, or if no such sequence exists because either
str is empty or it contains only whitespace characters, no conversion
is performed and zero is returned.
k = (k << 3) + (k << 1);
means
k = k * 2³ + k * 2¹ = k * 8 + k * 2 = k * 10
Does that help?
The *p - '0' term adds the value of the next digit; this works because C requires that the digit characters have consecutive values, so that '1' == '0' + 1, '2' == '0' + 2, etc.
As for your second question (atof), that should be its own question, and it's the subject for a thesis, not something simple to answer...
#include <stdio.h>
#include <errno.h>
#include <limits.h>
double atof(const char *string);
int debug=1;
int main(int argc, char **argv)
{
char *str1="3.14159",*str2="3",*str3="0.707106",*str4="-5.2";
double f1,f2,f3,f4;
if (debug) printf("convert %s, %s, %s, %s\n",str1,str2,str3,str4);
f1=atof(str1);
f2=atof(str2);
f3=atof(str3);
f4=atof(str4);
if (debug) printf("converted values=%f, %f, %f, %f\n",f1,f2,f3,f4);
if (argc > 1)
{
printf("string %s is floating point %f\n",argv[1],atof(argv[1]));
}
}
double atof(const char *string)
{
double result=0.0;
double multiplier=1;
double divisor=1.0;
int integer_portion=0;
if (!string) return result;
integer_portion=atoi(string);
result = (double)integer_portion;
if (debug) printf("so far %s looks like %f\n",string,result);
/* capture whether string is negative, don't use "result" as it could be 0 */
if (*string == '-')
{
result *= -1; /* won't care if it was 0 in integer portion */
multiplier = -1;
}
while (*string && (*string != '.'))
{
string++;
}
if (debug) printf("fractional part=%s\n",string);
// if we haven't hit end of string, go past the decimal point
if (*string)
{
string++;
if (debug) printf("first char after decimal=%c\n",*string);
}
while (*string)
{
if (*string < '0' || *string > '9') return result;
divisor *= 10.0;
result += (double)(*string - '0')/divisor;
if (debug) printf("result so far=%f\n",result);
string++;
}
return result*multiplier;
}
Interestingly, the man page for atoi doesn't indicate setting of errno so if you're talking any number > (2^31)-1, you're out of luck and similarly for numbers less than -2^31 (assuming 32-bit int). You'll get back an answer but it won't be what you want. Here's one that could take a range of -((2^31)-1) to (2^31)-1, and return INT_MIN (-(2^31)) if in error. errno could then be checked to see if it overflowed.
#include <stdio.h>
#include <errno.h> /* for errno */
#include <limits.h> /* for INT_MIN */
#include <string.h> /* for strerror */
extern int errno;
int debug=0;
int atoi(const char *c)
{
int previous_result=0, result=0;
int multiplier=1;
if (debug) printf("converting %s to integer\n",c?c:"");
if (c && *c == '-')
{
multiplier = -1;
c++;
}
else
{
multiplier = 1;
}
if (debug) printf("multiplier = %d\n",multiplier);
while (*c)
{
if (*c < '0' || *c > '9')
{
return result * multiplier;
}
result *= 10;
if (result < previous_result)
{
if (debug) printf("number overflowed - return INT_MIN, errno=%d\n",errno);
errno = EOVERFLOW;
return(INT_MIN);
}
else
{
previous_result *= 10;
}
if (debug) printf("%c\n",*c);
result += *c - '0';
if (result < previous_result)
{
if (debug) printf("number overflowed - return MIN_INT\n");
errno = EOVERFLOW;
return(INT_MIN);
}
else
{
previous_result += *c - '0';
}
c++;
}
return(result * multiplier);
}
int main(int argc,char **argv)
{
int result;
printf("INT_MIN=%d will be output when number too high or too low, and errno set\n",INT_MIN);
printf("string=%s, int=%d\n","563",atoi("563"));
printf("string=%s, int=%d\n","-563",atoi("-563"));
printf("string=%s, int=%d\n","-5a3",atoi("-5a3"));
if (argc > 1)
{
result=atoi(argv[1]);
printf("atoi(%s)=%d %s",argv[1],result,(result==INT_MIN)?", errno=":"",errno,strerror(errno));
if (errno) printf("%d - %s\n",errno,strerror(errno));
else printf("\n");
}
return(errno);
}
Here is my implementation(tested successfully with cases containing and starting with letters, +, - and zero's).
I tried to reverse-engineer atoi function in Visual Studio. If the input string only contained numerical characters, it could be implemented in one loop. but it gets complicated because you should take care of -,+ and letters.
int atoi(char *s)
{
int c=1, a=0, sign, start, end, base=1;
//Determine if the number is negative or positive
if (s[0] == '-')
sign = -1;
else if (s[0] <= '9' && s[0] >= '0')
sign = 1;
else if (s[0] == '+')
sign = 2;
//No further processing if it starts with a letter
else
return 0;
//Scanning the string to find the position of the last consecutive number
while (s[c] != '\n' && s[c] <= '9' && s[c] >= '0')
c++;
//Index of the last consecutive number from beginning
start = c - 1;
//Based on sign, index of the 1st number is set
if (sign==-1)
end = 1;
else if (sign==1)
end = 0;
//When it starts with +, it is actually positive but with a different index
//for the 1st number
else
{
end = 1;
sign = 1;
}
//This the main loop of algorithm which generates the absolute value of the
//number from consecutive numerical characters.
for (int i = start; i >=end ; i--)
{
a += (s[i]-'0') * base;
base *= 10;
}
//The correct sign of generated absolute value is applied
return sign*a;
}
about atoi() hint code from here:
and based on the atoi(), my implementation of atof():
[have same limitation of original code, doesn't check length, etc]
double atof(const char* s)
{
double value_h = 0;
double value_l = 0;
double sign = 1;
if (*s == '+' || *s == '-')
{
if (*s == '-') sign = -1;
++s;
}
while (*s >= 0x30 && *s <= 0x39)
{
value_h *= 10;
value_h += (double)(*s - 0x30);
++s;
}
// 0x2E == '.'
if (*s == 0x2E)
{
double divider = 1;
++s;
while (*s >= 0x30 && *s <= 0x39)
{
divider *= 10;
value_l *= 10;
value_l += (double)(*s - 0x30);
++s;
}
return (value_h + value_l/divider) * sign;
}
else
{
return value_h * sign;
}
}

Resources