I have seen other solutions to this problem where a pointer is used. I don't understand the workings of a pointer enough to implement them into this program. If the solution requires one, would someone please be able to explain why? I have been trying various things with this program all night and gotten nowhere. I read the relevant text in 'The C Programming Language' book, where the exercise is from. I can't be the only person stumped by this D:
#include <stdio.h>
#include <math.h>
#include <ctype.h>
#define MAX 1000
int htoi(char s[]);
main()
{
char line[MAX];
int i, c;
printf("Enter the strig to convert to an integer:");
for(i=0; i<MAX && (c=getchar())!=EOF && c != '\n'; ++i)
line[i] = c;
int a =0;
a = htoi(line);
printf("%d", a);
}
int htoi(char s[])
{
int i, n, z;
n=0;
int total = 0;
for(i=0; s[i] != '\0'; ++i)
{
if (s[i] == 'a'||s[i] == 'A')
n = 10;
else if(s[i] == 'b'||s[i] == 'B')
n = 11;
else if(s[i] == 'c'||s[i] == 'C')
n = 12;
else if(s[i] == 'd'||s[i] == 'D')
n = 13;
else if(s[i] == 'e'||s[i] == 'E')
n = 14;
else if(s[i] == 'f'||s[i] == 'F')
n = 15;
else
n = s[i];
z = n * pow(16, i);
total = total + z;
}
return total;
}
Someone correct me if I am wrong. But you're not putting a null terminator in your char array:
for(i=0; i<MAX && (c=getchar())!=EOF && c != '\n'; ++i)
line[i] = c;
Later on, you do
for(i=0; s[i] != '\0'; ++i)
But since you never appended a null terminator the above for loop will iterate PAST the bounds of the array until it sees a null somewhere on the stack or it segfaults.
you should be doing the following:
for(i=0; i<(MAX-1) && (c=getchar())!=EOF && c != '\n'; ++i)
line[i] = c;
line[i+1] = '\0';
Note the (MAX-1)
P.S Don't run anything that doesn't require root as root, see: least privilege principle
Your problem is here:
else
n = s[i]; // <- n is getting the character code value of S[i]
To solve, I suggest to do:
else
n = s[i] - '0';
EDITED:
You have two problems else:
You need to null terminate the line char (your string hasn't '\0')
You are inverting the power math (digit more at left are more significants than at right position)
To solve (1), do that:
for(i=0; i<MAX && (c=getchar())!=EOF && c != '\n'; ++i)
line[i] = c;
line[i] = '\0'; // <-- added here
To solve (2), do that:
int total = 0;
int len = strlen(s) - 1; // <- added here
...
z = n * pow(16, len - i); // <- change here
Another way, you can avoid using the expensive pow function by just shifting 4 bits to left as in code bellow:
instead of:
z = n * pow(16, i);
total = total + z;
do:
total <<= 4; // changed here
total += n; // and here
Related
The code below does not work as expected, somebody can give me some suggestions?
#include <stdio.h>
int main(){
int i, k=0, j=0;
char hex[50], c;
for (i=0; (c=getchar()) != EOF && (c=getchar()) != '\n'; i++) {
hex[i] = c;
j++;
}
if (c == 'n') {
hex[i] = 'n';
i++;
}
hex[i] = '\0';
for (k=0; k<i; k++) {
printf("%c", hex[k]);
}
printf("\n%d %d %d\n", i, j, k);
return 0;
}
if I input:
abc
I suppose the output should be:
abc
4 3 4
However, in my Xcode IDE the output is:
b
1 1 1
Somebody can help me to debug my code?
When you say
for (i=0; (c=getchar()) != EOF && (c=getchar()) != '\n'; i++)
compiler evaluates c=getchar()) != EOF first and takes the first char as input. Then if it is true it evaluates (c=getchar()) != '\n'. Now value of c is 'b'.
You should say
for (i=0; (c=getchar()) != EOF && c != '\n'; i++)
because c is already initialized as 'a'
EDIT: as #Stargateur says you should use while when you don't know how long the operation goes and when you are waiting for some input to end it. Use for loop for restricted operations like operating on known number of items (for example array of a struct).
fix like this
#include <stdio.h>
int main(void){
int i, j, k, c;//The type of c must be int.
char hex[50];
for (j = i = 0; i < sizeof(hex)-1 && (c=getchar()) != EOF && c != '\n'; i++, j++) {//The input part should be one.
hex[i] = c;
}
if (c == '\n') {//n is typo as \n
hex[i] = '\n';
i++;
}
hex[i] = '\0';
for (k = 0; k < i; k++) {
printf("%c", hex[k]);
}
printf("%d %d %d\n", i, j, k);//newline already include.
return 0;
}
I have been learning from the C Programming Language book (K&R) and was writing one of the exercises that removes trailing blanks from an input. I understand that a segmentation fault is at some level a problem having to do with accessing memory that is not accessible, but I have read through this code several times and can't find the error. I would like it very much if someone could help find this error and tell me how to discover errors like this in the future.
#include <stdio.h>
#define MAXLINE 1000
#define CHAR 0 /*character definition*/
#define TRAIL 1 /*determines whether program is in a trailing blank*/
int getinput(char input[], int max);
int trailrem(char input[], char copyto[]);
int len;
int main() {
char line[MAXLINE]; /*current line*/
char newline[MAXLINE];
int i, c, newreturn; /*integer counter, character holder, current line length, and trailrem return value*/
int len;
while((len = getinput(line, MAXLINE)) > 0) {
newreturn = trailrem(line, newline);
for(i = 0; i <= newreturn; ++i)
printf("\n%c\n", newline[i]);
}
}
int getinput(char input[],int max) {
int i, c, line;
for(i = 0; (c = getchar()) != EOF && c != '\n' && c < (max-1); ++i)
input[i] = c;
if(c == '\n') {
input[i] = c;
++i;
}
input[i] = '\0';
return i;
}
int trailrem(char input[], char copy[]) {
int i, j, minusin, state, r;
for(i = len; input[i] != EOF && i >= 0; --i) {
if(input[i] =='\n')
state = TRAIL;
else if((input[i] == ' ' && state == TRAIL) ||( input[i] == '\t' && state == TRAIL))
++minusin;
else if(state == TRAIL && (input[i] != ' ' || input[i] != '\t'))
state = CHAR;
for(j = (r = len-minusin); state == CHAR; --j){
copy[j-2] = input[i];
}
}
copy[r] = '\0';
copy[r-1] = '\n';
return r;
}
So many problems in your code. But the main problem is, you have a global len
int len;
And a local len in the main function.
You are initializing len in main function like this:
while((len = getinput(line, MAXLINE)) > 0)
So the local len is updated. But the global len is still 0.
You are expecting that, you will get the updated value of len in trailrem method but you don't. In trailrem() you will get len equal to 0!
for(i = len; input[i] != EOF && i >= 0; --i)
So i is 0 too. And hence, copy[r-1] = '\n'; will crash, because r-1 can be negative.
Other problems: (BLUEPIXY and WhozCraig mentioned in the comment).
for(i = 0; (c = getchar()) != EOF && c != '\n' && c < (max-1); ++i)
here, c < (max-1) should be i < (max-1).
++minusin; in trailrem function where minusin is uninitialized.
i'm newbie in C programming .
i have written this code for adding two numbers with 100 digits , but i don't know why the code does not work correctly , it suppose to move the carry but it doesn't .
and the other problem is its just ignoring the first digit (most significant digit) .
can anybody help me please ?
#include <stdio.h>
#include <ctype.h>
int sum[101] = {0};
int add(int a, int b);
void main()
{
static int a[100];
static int b[100];
char ch;
int i = 0;
int t;
for (t = 0; t != 100; ++t)
{
a[t] = 0;
}
for (t = 0; t != 100; ++t)
{
b[t] = 0;
}
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
a[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
i = 0;
do
{
ch = fgetc(stdin);
if ( isdigit(ch) )
{
b[i] = ch - 48;
++i;
}
else
break;
}
while (ch != '\n' || i == 100 || i != '\0');
for (;i!=0; --i)
{
add(a[i], b[i]);
}
for (i==0;i != 101; ++i)
{
printf("%d", sum[i]);
}
}
int add( int a , int b)
{
static int carry = 0;
float s = 0;
static int p = 101;
if (0 <= a+b+carry <= 9)
{
sum[p] = (a + b + carry);
carry = 0;
--p;
return 0;
}
else
{
if (10 <= a+b+carry < 20)
{
s = (((a+b+carry)/10.0 ) - 1) * 10 ;
carry = ((a+b+carry)/10.0) - (s/10);
}
else
{
s = (((a+b+carry)/10 ) - 2) * 10;
carry = ((a+b+carry)/10.0) - (s/10);
}
sum[p] = s;
--p;
return 0;
}
}
Your input loops have serious problem. Also you use i to count the length of both a and b, but you don't store the length of a. So if they type two numbers that are not equal length then you will get strange results.
The losing of the first digit is because of the loop:
for (;i!=0; --i)
This will execute for values i, i-1, i-2, ..., 1. It never executes with i == 0. The order of operations at the end of each iteration of a for loop is:
apply the third condition --i
test the second condition i != 0
if test succeeded, enter loop body
Here is some fixed up code:
int a_len;
for (a_len = 0; a_len != 100; ++a_len)
{
int ch = fgetc(stdin); // IMPORTANT: int, not char
if ( ch == '\n' || ch == EOF )
break;
a[a_len] = ch;
}
Similarly for b. In fact it would be a smart idea to make this code be a function, instead of copy-pasting it and changing a to b.
Once the input is complete, then you could write:
if ( a_len != b_len )
{
fprintf(stderr, "My program doesn't support numbers of different length yet\n");
exit(EXIT_FAILURE);
}
for (int i = a_len - 1; i >= 0; --i)
{
add(a[i], b[i]);
}
Moving onto the add function there are more serious problems here:
It's not even possible to hit the case of sum being 20
Do not use floating point, it introduces inaccuracies. Instead, doing s = a+b+carry - 10; carry = 1; achieves what you want.
You write out of bounds of sum: an array of size [101] has valid indices 0 through 100. But p starts at 101.
NB. The way that large-number code normally tackles the problems of different size input, and some other problems, is to have a[0] be the least-significant digit; then you can just expand into the unused places as far as you need to go when you are adding or multiplying.
I'm making a program that takes the characters from congress.txt makes them all uppercase, then "shifts them two characters", (A goes to C) (Z goes to B). But nothing is being printed, my main concern is if my arrays are being stored and passed to the different functions properly.
This is what is in congress.txt:
Congress shall make no law respecting an establishment of religion, or prohibiting the free exercise thereof; or abridging the freedom of speech, or of the press; or the right of the people peaceably to assemble, and to petition the government for a redress of grievances.
#include<stdio.h>
int processFile(int *store);
int cipher(int *store, int *code);
int outputCode(int *code);
int main(void){
int store[300], code[300], i;
processFile(store);
cipher(store, code);
outputCode(code);
getchar();
return 0;
}
void processFile(int *store){
int i, a = 0;
FILE *f = fopen("congress.txt", "r");
for (i = 0; a != EOF;){
fscanf(f, "%c", &a); //store character in a
if (a <= 'Z' && a >= 'A'){ //store uppercase letters
store[i] = a;
i++;
}
if (a <= 'z' && a >= 'a'){ //store lowercase letters as uppercase
store[i] = a - 32;
i++;
}
}
i++;
store[i] = '\0';
}
void cipher(int *store, int *code){
int i;
for (i = 0; store[i] != 0; ++i){
if (store[i] <= 'X' && store[i] >= 'A'){ //tests to see if the letter is between A and X
code[i] = (char)(store[i] + 2); //shifts letter by two characters
}
if (store[i] >= 'Y' && store[i] <= 'Z'){
code[i] = (char)(store[i] - 24); //shifts Y and Z to A or B respectively
}
}
}
void outputCode(int *code){
int i, a, b;
for (a = 0; code[a] != 0; ++a){
if (!(a % 50)){ //makes a newline every 50 characters
printf("\n");
}
for (b = 0; code[a] != 0 && b <= 5; ++b){ //prints chunks of 5 characters then makes a space
printf("%c", code[a]);
}
printf(" ");
}
}
There are several things wrong with your code - many of which your compiler will complain about.
To start - you don't have return values for functions that are declared int. Just make them void, or return something.
Second - you declare int a; but proceed to use it like a char. Declare it how you use it.
Third - testing for end of file is done with feof(f) not a != EOF.
Fourth - when you output your code you need to increment a, otherwise you get the same value five times:
VVVVVV JJJJJJ KKKKKK UUUUUU KKKKKK UUUUUU UUUUUU
etc.
Fifth - your printing routine doesn't guarantee it will stop - if you have a single '\0' followed by other garbage, you will print more garbage (unless it happens on a multiple of 5). You need to pad your cipher with zeros.
So - working code:
#include<stdio.h>
int processFile(int *store);
int cipher(int *store, int *code);
int outputCode(int *code);
int main(void){
int store[300], code[300], i;
processFile(store);
cipher(store, code);
outputCode(code);
printf("\n=====\n\n");
return 0;
}
int processFile(int *store){
int i;
char a = 0;
FILE *f = fopen("congress.txt", "r");
for (i = 0; !feof(f) && i<299;){
fscanf(f, "%c", &a); //store character in a
if (a <= 'Z' && a >= 'A'){ //store uppercase letters
store[i] = a;
i++;
}
if (a <= 'z' && a >= 'a'){ //store lowercase letters as uppercase
store[i] = a - 32;
i++;
}
}
store[i]='\0';
return 0;
}
int cipher(int *store, int *code){
int i;
for (i = 0; store[i] != 0; ++i){
if (store[i] <= 'X' && store[i] >= 'A'){ //tests to see if the letter is between A and X
code[i] = (char)(store[i] + 2); //shifts letter by two characters
}
if (store[i] >= 'Y' && store[i] <= 'Z'){
code[i] = (char)(store[i] - 24); //shifts Y and Z to A or B respectively
}
}
for(; i<300; i++) code[i]=0; // pad with zeros
return 0;
}
int outputCode(int *code){
int i, a, b;
for (a = 0; code[a] != 0; ++a){
if (!(a % 50)){ //makes a newline every 50 characters
printf("\n");
}
for (b = 0; code[a] != 0 && b <= 5; ++b){ //prints chunks of 5 characters then makes a space
printf("%c", code[a++]);
}
printf(" ");
}
return 0;
}
Hi this is my first question here so I apologize if I didn't follow all the rules for posting. This is K&R exercise 2-3 and I'm getting a segmentation fault when compiling with GCC and I'm not familiar with the debugger to understand what's going on. I'd be grateful if anyone could glance over the code and help me with what went wrong.
#include <stdio.h>
#define HEX 16
unsigned int htoi(char s[]) {
int i, len, n, rp, v;
v = 0;
if (s[0] == '0')
if (s[1] == 'x' || s[1] == 'X')
s[1] = '0';
for (len = 0; len != '\0'; ++len) {
}
for (i = len; i >= 0; --i) {
if (s[i] >= '0' && s[i] <= '9')
n = s[i] - '0';
else if (s[i] >= 'A' && s[i] <= 'F')
n = s[i] - 'A' + 10;
else if (s[i] >= 'a' && s[i] <= 'f')
n = s[i] - 'a' + 10;
rp = len - i;
v += n * HEX^rp;
}
return v;
}
int main() {
int test = htoi("0x1a9f");
printf("%d\n", test);
return 0;
}
You are passing the address of a string literal which is read-only. Doing the following will get rid of the segmentation fault.
char temp[] = "0x1a9f";
int test = htoi(temp);
Also:
v += n * HEX^rp;
Is ^ is the XOR operator and not the power operator. For power you need the pow function in math.h
Also:
for (i = len; i >= 0; --i) should be for (i = len - 1; i >= 0; --i) because the value of len goes out of the bound of the array. (Notified by #Grijesh Chauhan and #simonc)
int test = htoi("0x1a9f");
passes the string literal "0x1a9f" to htoi. This may exist in read-only memory and cannot be modified. You therefore get undefined behaviour (with a crash a valid example of this) when you try to write to the string in the line
s[1] = '0';
The easiest fix is to copy the original string into a modifiable variable
char s[] = "0x1a9f";
int test = htoi(s);
As reported by Grijesh, further into htoi, you also read beyond the bounds of the string
for (i = len; i >= 0; --i)
should be:
for (i = len - 1; i >= 0; --i)