atoi function doesn't work in for loop - c

I am trying to get the output of this equation :
44 - 10 + 11 / 5
it work properly as follow :
char str[] = "44 - 10 + 11 / 5";
int sum = 0 ;
sum += atoi(str); // 0 + 44
sum += atoi(str+3); // 44 + 10
sum += atoi(str+5); // 54 + 11
sum += atoi(str+7); // 65 / 5 = 13
printf("%d/n",sum); // output = 13
but it doesn't work if I put the atoi() function in the for loop:
char str[] = "44 - 10 + 11 / 5";
int sum = 0;
int i;
sum += atoi(str);
for (i = 0; i < 100; i++) {
if (!(str[i] >= 0 && str[i] <= 9)) { //if str[i] is not a number
sum += atoi(str + i);
}
}
printf("%d/n", sum); // output = 0

You are comparing a char value that contains the ASCII representation of a number, to an actual number. Change
if(!(str[i]>=0 && str[i]<=9)){
to
if(!(str[i]>='0' && str[i]<='9')){
I did not check if the rest of the code is correct, but certainly, this is one issue.

if(!(str[i]>=0 && str[i]<=9)){ //if str[i] is not a number
This is incorrect. '0' and 0 are not same. Neither is 9 and '9'. The value of '9' will be integer that represents '9' in ASCII chart.
Rest of the logic seems suspicious too, for example what happens if you have "55", code will enter if twice, once for 55 and second time for 5, isn't it?

Because your code does not do the same calculations as your previous one. In the first one you are shifting the pointer to the next number and you are adding it to the number, so your code does the following 44 + 10 + 11 + 5.
In the second case you are checking whether the character code is between 0 and 9, but the numbers are between 48 and 57 - the characters '0' and '9'. So the if statement would be always wrong. Your intention was probably this, but it won't work.
for(i = 0; i < 100 ; i++){
if(!(str[i]>='0' && str[i]<='9')){ //if str[i] is not a number
sum += atoi(str+i);
}
}
This also does not work, because here you are doing the wrong shifts of the pointer by one, resulting in the reading of the following numbers: 44, 4, 10, 0, 11, 1, 5. Because of the atoi properties. To perform the exact same code you did before you`d have to write the following code:
int skip_non_diggits(int i, char *str) {
while (str[i] < '0' || str[i] > '9') {
if (str[i] == 0)
return -1; //end of string case
i++;
}
return i;
}
int skip_diggits(int i, char *str) {
while (str[i] >= '0' && str[i] <= '9') {
if (str[i] == 0)
return -1; //end of string case
i++;
}
return i;
}
These functions could be used as follows:
int i = 0, sum = 0;
while (i != -1) {
sum += atoi(str+i);
i = skip_diggits(i, str); // positions i after the current number
i = skip_non_diggits(i, str); // positions i at the begin of the next number
}
BTW
Don't use for (i = 0; i < 100; i++) to iterate through the strings you don't know the size of. If the string is shorter in length than 100 you're derefferencing memory which probably isn't yours creating undefined behavior. Instead check the strlen method or check whether the character is not equal to \0 which in C indicates the end of the string.

This seems a bit odd. What's the goal?
Agree with previous comment.
Why are you doing atoi() on what is NOT a number?
You will go past the end of the string.
Your spaces COUNT in the example
and so on.
you don't update i when you find a number, so you will count "44" as 44 first and 4 second.
If you're trying to learn, hook up a debugger, step through the code, and see how the data changes.

Related

Trying to re-index ASCII to 0,1,2,34, etc

I'm trying to re-index my ASCII decimal characters of the alphabet so that they start at 0 with 'A' rather than 65 so I can use a certain formula.
My initial thoughts were to create a string of the alphabet and iterate over it taking away minus 65 at each iteration, I then realised this is only having an effect on the string (which gives a segfault anyway) and does not have any effect on the decimal value of the actual character:
string alphabet = "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz";
for (int k = 0, length_ = strlen(alphabet); k < length_ ; k ++)
{
alphabet[k] = alphabet[k] - 65;
printf("Alphabet no.%i is equal to %c", k, alphabet[k]);
}
Any ideas?
void printAlpha(int i){
if(i < 26)
printf("%c", 'A' + i);
else if(i < 52)
printf("%c", i - 26 + 'a');
}

Brute force function for decrypting string in C (Caesar cipher )

I found this problem interesting, as it is given that you need to use the alphabet as an array in C. Task is to brute force every possible K value, in basic Caesar's cipher manner.
However, code I come up with compile non-true values after K = 1. For example, a letter C is turned to Z instead of A etc. Can anyone spot what I did wrong?
#include <stdio.h>
#include <string.h>
void bruteforce (char*);
int main() {
char cyphertext[] = "kyvtrmrcipnzccrkkrtbwifdkyvefikynvjkrkeffe";
bruteforce(cyphertext);
return 0;
}
void bruteforce (char *cyphertext) {
char alphabet[26] = "abcdefghijklmnopqrstuvwxyz";
long int size = strlen(cyphertext);
for (int k = 0; k < 26; k++){
for (long int i = 0; i < size; i++){
for (int j = 0; j < 26; j++){
if (alphabet[j] == cyphertext[i]){
cyphertext[i] = alphabet[j - k];
if (k > j){
cyphertext[i] = alphabet[26 + j - k];
}
break;
}
}
}
printf("%s\n ", cyphertext);
}
}
For Caesar Cypher shifting, you don't need to use the alphabet string. You can just shift the character in ASCII code. ASCII codes of 'a' - 'z' are 97 - 122. Thus if decode with + 1. If the characters are a - z, you can just add one to each character. If after adding the shift value to the character value and the character value become larger than 122 then take the character value and subtract it to 122 then add 96 to that.
For shifting negative, if character value become smaller than 97. Take 97 subtract to character's value. Then subtract 123 to the previous equation value. Nonetheless, I built the code so that negative shift will be convert to positive shift. If the shift is negative we take 26 and add to that. Example is, shifting -1 will make a become z. So that is similar to shifting 26 + -1 = 25.
Shift value can be larger than +25 or smaller than -25. Nonetheless, if it is, it will be modulus to 26.
If you want to bruteforce all the possible combinations for a string. Just use the function below and run it in a loop from 1 to 25. But your function modify the original string. Thus, when doing bruteforce, you would have to copy the string of your function to a temporary string and let the function work on that. The examples are below.
#include <stdio.h>
#include <string.h>
void bruteforce (char *cyphertext, int shiftBy);
int main() {
char cyphertext[] = "kyvtrmrcipnzccrkkrtbwifdkyvefikynvjkrkeffe";
char cyphertext2[] = "yvccf wifd bvmze";
bruteforce(cyphertext, -17);
puts("");
bruteforce(cyphertext2, 9);
/* Bruteforce example */
puts("");
puts("Bruteforce section:");
// +9
char cyphertext3[] = "kyzjkvokzjkfsvtirtb nyrk tre kyzj sv zj zk yvccf nficu";
char temp[50];
for (int i = 1; i < 26; i++){
printf("Trying to crack by shifting %d \n", i );
strcpy(temp, cyphertext3);
bruteforce(temp, i);
puts("");
}
/* End Bruteforce example */
return 0;
}
// If there is no shift i.e 0, 26, 52, -26
// It won't print
void bruteforce (char *cyphertext, int shiftBy){
size_t size = strlen(cyphertext);
if ( shiftBy > 25){
shiftBy = shiftBy % 26;
} else if ( shiftBy < 0 ) {
shiftBy = 26 + (shiftBy % 26);
// If shiftBy is 26
// there is no need to shift.
if ( shiftBy == 26 ) return;
}
// If there is no shift return.
if ( shiftBy == 0 ) return;
for ( size_t i = 0; i < size; i++){
// 97 - 122 is a - z
// if char is a - z
if ( cyphertext[i] > 96 && cyphertext[i] < 123 ){
// add shift by
cyphertext[i] += shiftBy;
// if char > z
// then take char - z then add to the ascii code that just before 'a'.
// Since shiftBy is converted fomr negative to positive.,
// There will not be a negative shiftBy.
if ( (unsigned char)cyphertext[i] > 122 )
cyphertext[i] = ((unsigned char) cyphertext[i]) - 122 + 96;
}
// If want to do A - Z
// ASCII code are 65 - 90.
}
printf("%s\n", cyphertext);
}

Parsing a CSV File Problems

I tried this to parse data given in a csv file into ID, AGE, and GPA fields in a "data" file, but I don't think I'm doing this right (when I tried printing the data, its printing weird numbers). What am I doing wrong?
char data[1000];
FILE *x = fopen("database.csv","rt");
char NAME[300];
int ID[300],AGE[300],GPA[300];
int i,j;
i = 0;
while(!feof(x)) {
fgets(data,999,x);
for (j = 0; j < 300 && data[i] != ','; j++, i++) {
ID[j] = data[i];
i++;
}
for (j = 0; j < 300 && data[i] != ','; j++, i++) {
NAME[j] = data[i];
i++;
}
for (j = 0; j < 300 && ( data[i] != '\0' || data[i] != '\r' || data[i] != data[i] != '\n'); j++, i++) {
GPA[j] = data[i];
}
}
First of all: for what you're doing, you probably want to look carefully at the function strtok and the atoi macro. But given the code you posted, that's perhaps still a bit too advanced, so I'm taking a longer way here.
Supposing that the line is something like
172,924,1182
then you need to parse those numbers. The number 172 is actually represented by two or four bytes in memory, in a very different format, and the byte "0" is nothing like the number 0. What you'll read is the ASCII code, which is 48 in decimal, or 0x30 in hex.
If you take the ASCII value of a single digit and subtract 48, you will get a number, because fortunately the numbers are stored in digit order, so "0" is 48, "1" is 49 and so on.
But you still have the problem of converting the three digits 1 7 2 into 172.
So once you have 'data':
(I have added commented code to deal with a unquoted, unescaped text field inside the CSV, since in your question you mention an AGE field, but then you seem to want to use a NAME field. The case when the text field is quoted or escaped is another can of worms entirely)
size_t i = 0;
int number = 0;
int c;
int field = 0; // Fields start at 0 (ID).
// size_t x = 0;
// A for loop that never ends until we issue a "break"
for(;;) {
c = data[i++];
// What character did we just read?
if ((',' == c) || (0x0c == c) || (0x0a == c) || (0x00 == c)) {
// We have completed read of a number field. Which field was it?
switch(field) {
case 0: ID[j] = number; break;
case 1: AGE[j] = number; break;
// case 1: NAME[j][x] = 0; break; // we have already read in NAME, but we need the ASCIIZ string terminator.
case 2: GPA[j] = number; break;
}
// Are we at the end of line?
if ((0x0a == c) || (0x0c == c)) {
// Yes, break the cycle and read the next line
break;
}
// Read the next field. Reinitialize number.
field++;
number = 0;
// x = 0; // if we had another text field
continue;
}
// Each time we get a digit, the old value of number is shifted one order of magnitude, and c gets added. This is called Horner's algorithm:
// Number Read You get
// 0 "1" 0*10+1 = 1
// 1 "7" 1*10+7 = 17
// 17 "2" 17*10+2 = 172
// 172 "," Finished. Store 172 in the appropriate place.
if (c >= '0' && c <= '9') {
number = number * 10 + (c - '0');
}
/*
switch (field) {
case 1:
NAME[j][x++] = c;
break;
}
*/
}

I need to add string characters in C. A + B must = C. Literally

I am writing a program that is due tonight at midnight, and I am utterly stuck. The program is written in C, and takes input from the user in the form SOS where S = a string of characters, O = an operator (I.E. '+', '-', '*', '/'). The example input and output in the book is the following:
Input> abc+aab
Output: abc + aab => bce
And that's literally, not variable. Like, a + a must = b.
What is the code to do this operation? I will post the code I have so far, however all it does is take the input and divide it between each part.
#include <stdio.h>
#include <string.h>
int main() {
system("clear");
char in[20], s1[10], s2[10], o[2], ans[15];
while(1) {
printf("\nInput> ");
scanf("%s", in);
if (in[0] == 'q' && in[1] == 'u' && in[2] == 'i' && in[3] == 't') {
system("clear");
return 0;
}
int i, hold, breakNum;
for (i = 0; i < 20; i++) {
if (in[i] == '+' || in[i] == '-' || in[i] == '/' || in[i] == '*') {
hold = i;
}
if (in[i] == '\0') {
breakNum = i;
}
}
int j;
for (j = 0; j < hold; j++) {
s1[j] = in[j];
}
s1[hold] = '\0';
o[0] = in[hold];
o[1] = '\0';
int k;
int l = 0;
for (k = (hold + 1); k < breakNum; k++) {
s2[l] = in[k];
l++;
}
s2[breakNum] = '\0';
printf("%s %s %s =>\n", s1, o, s2);
}
}
Since this is homework, let's focus on how to solve this, rather than providing a bunch of code which I suspect your instructor would frown upon.
First, don't do everything from within the main() function. Break it up into smaller functions each of which do part of the task.
Second, break the task into its component pieces and write out the pseudocode:
while ( 1 )
{
// read input "abc + def"
// convert input into tokens "abc", "+", "def"
// evaluate tokens 1 and 3 as operands ("abc" -> 123, "def" -> 456)
// perform the operation indicated by token 2
// format the result as a series of characters (579 -> "egi")
}
Finally, write each of the functions. Of course, if you stumble upon roadblocks along the way, be sure to come back to ask your specific questions.
Based on your examples, it appears “a” acts like 1, “b” acts like 2, and so on. Given this, you can perform the arithmetic on individual characters like this:
// Map character from first string to an integer.
int c1 = s1[j] - 'a' + 1;
// Map character from second string to an integer.
int c2 = s2[j] - 'a' + 1;
// Perform operation.
int result = c1 + c2;
// Map result to a character.
char c = result - 1 + 'a';
There are some things you have to add to this:
You have to put this in a loop, to do it for each character in the strings.
You have to vary the operation according to the operator specified in the input.
You have to do something with each result, likely printing it.
You have to do something about results that extended beyond the alphabet, like “y+y”, “a-b”, or “a/b”.
If we assume, from your example answer, that a is going to be the representation of 1, then you can find the representation values of all the other values and subtract the value representation of a from it.
for (i = 0; i < str_len; i++) {
int s1Int = (int)s1[i];
int s2Int = (int)s1[i];
int addAmount = 1 + abs((int)'a' - s2Int);
output[i] = (char)(s1Int + addAmount)
}
Steps
1) For the length of the s1 or s2
2) Retrieve the decimal value of the first char
3) Retrieve the decimal value of the second char
4) Find the difference between the letter a (97) and the second char + 1 <-- assuming a is the representation of 1
5) Add the difference to the s1 char and convert the decimal representation back to a character.
Example 1:
if S1 char is a, S2 char is b:
s1Int = 97
s2Int = 98
addAmount = abs((int)'a' - s2Int)) = 1 + abs(97 - 98) = 2
output = s1Int + addAmount = 97 + 2 = 99 = c
Example 2:
if S1 char is c, S2 char is a:
s1Int = 99
s2Int = 97
addAmount = abs((int)'a' - s2Int)) = 1 + abs(97 - 97) = 1
output = s1Int + addAmount = 99 + 1 = 100 = d

Data types conversion (unsigned long long to char)

Can anyone tell me what is wrong with the following code?
__inline__
char* ut_byte_to_long (ulint nb) {
char* a = malloc(sizeof(nb));
int i = 0;
for (i=0;i<sizeof(nb);i++) {
a[i] = (nb>>(i*8)) & 0xFF;
}
return a;
}
This string is then concatenated as part of a larger one using strcat. The string prints fine but for the integers which are represented as character symbols. I'm using %s and fprintf to check the result.
Thanks a lot.
EDIT
I took one of the comments below (I was adding the terminating \0 separately, before calling fprintf, but after strcat. Modifying my initial function...
__inline__
char* ut_byte_to_long (ulint nb) {
char* a = malloc(sizeof(nb) + 1);
int i = 0;
for (i=0;i<sizeof(nb);i++) {
a[i] = (nb>>(i*8)) & 0xFF;
}
a[nb] = '\0' ;
return a;
}
This sample code still isn't printing out a number...
char* tmp;
tmp = ut_byte_to_long(start->id);
fprintf(stderr, "Value of node is %s \n ", tmp);
strcat is expecting a null byte terminating the string.
Change your malloc size to sizeof(nb) + 1 and append '\0' to the end.
You have two problems.
The first is that the character array a contains numbers, such as 2, instead of ASCII codes representing those numbers, such as '2' (=50 on ASCII, might be different in other systems). Try modifying your code to
a[i] = (nb>>(i*8)) & 0xFF + '0';
The second problem is that the result of the above computation can be anything between 0 and 255, or in other words, a number which requires more than one digit to print.
If you want to print hexadecimal numbers (0-9, A-F), two digits per such computation will be enough, and you can write something like
a[2*i + 0] = int2hex( (nb>>(i*8)) & 0x0F ); //right hexa digit
a[2*i + 1] = int2hex( (nb>>(i*8+4)) & 0x0F ); //left hexa digit
where
char int2hex(int n) {
if (n <= 9 && n >= 0)
return n + '0';
else
return (n-10) + 'A';
}
if you dont want to use sprintf(target_string,"%lu",source_int) or the non standard itoa(), here is a version of the function that transform a long to a string :
__inline__
char* ut_byte_to_long (ulint nb) {
char* a = (char*) malloc(22*sizeof(char));
int i=21;
int j;
do
{
i--;
a[i] = nb % 10 + '0';
nb = nb/10;
}while (nb > 0);
// the number is stored from a[i] to a[21]
//shifting the string to a[0] : a[21-i]
for(j = 0 ; j < 21 && i < 21 ; j++ , i++)
{
a[j] = a[i];
}
a[j] = '\0';
return a;
}
I assumed that an unsigned long contain less than 21 digits. (biggest number is 18,446,744,073,709,551,615 which equals 2^64 − 1 : 20 digits)

Resources