in the following simple reverse function I'm always off by one, meaning the first character passed in is never printed last like it should be:
void reverse(char * c)
{
if(*c != '\0')
{
reverse(++c);
printf("%c", *c);
}
else {
return;
}
}
yet when I change the call to reverse to be c+1, everything works fine. Any ideas as to why, the unary pre-increment operator should be doing exactly the same as c + 1. I know a recursive function isn't the best performing way to go about this problem but I'm just experimenting at the moment. Thanks!
Because c+1 does not change c whereas ++c does.
Think about this when c is pointing to address 1234:
reverse(++c); // c is now 1235 and you pass that.
printf("%c", *c); // so we print the second character at 1235.
With the c+1 version:
reverse(c+1); // c is still 1234 but you pass 1235.
printf("%c", *c); // so we print the first character at 1234.
For what it's worth, your reverse function is needlessly complicated.The else return is redundant and I personally prefer recursion calls that check terminating conditions first since I've often found these are usually easier for compilers to do tail-end recursion optimisations on.
The following complete test program shows you the way I'd do it:
#include <stdio.h>
void reverse (char *c) {
if (*c == '\0') return;
reverse (c + 1);
putchar (*c);
}
int main (int argc, char *argv[]) {
int i;
for (i = 1; i < argc; i++) {
reverse (argv[i]);
putchar ('\n');
}
return 0;
}
Running this with testprog hello goodbye gives you:
olleh
eybdoog
No the unary pre-increment is not the same like addition by one.
f(++c) is equivalent to
c = c + 1
f(c);
whereas f(c+1) is equivalent to
auto d = c + 1;
f(d);
And just for completeness: f(c++) is the same like
f(c);
c = c+1;
However sequence points matter, e.g. if(c++ > 0 && c++ < 10) would evaluate like
auto a = c;
c = c + 1;
auto b = c;
c = c + 1;
if(a > 0 || b < 10) { /* ... */ }
and consequently preincrement
c = c + 1;
auto a = c;
c = c + 1;
auto b = c;
if(a > 0 || b < 10) { /* ... */ }
Calling with c + 1 won't change the value of c in the local context (the one used when printing *c), but using ++c in the call will.
No, it doesn't do the same thing.
It increments it then sends it to your function.
when you put c+1, it doesn't change the value of c, but ++c does change the value of c.. as an example for difference between pre and post increment operators:
int a = 1;
int b = ++a;
// Now a is 2 and b is also 2.
int a = 1;
int b = a++;
// Now a is 2 but b is 1.
FIXED: You shouldn't use increment operator. Operator+ would be better.:
reverse(c + 1);
printf("%c", *c);
Related
Is it possible to get the same results as this code using only a and b?
I'm trying to calculate c from a and b to avoid using a third variable, but I can't find a solution.
#include <stdio.h>
#include <stdlib.h>
const int LENGTH = 20;
int main()
{
char arr[LENGTH];
for (int a = 0, b = 1, c = 0; c < LENGTH; c++) {
if (a < b) {
arr[c] = '*';
a++;
} else {
arr[c] = ' ';
a = 0;
b++;
}
}
printf(arr);
return EXIT_SUCCESS;
}
Code result : * ** *** **** *****
In the event that checking if a number is triangular by linking or writing some sort of sqrt() function is not a solution that you find acceptable:
Each group of **... in the final string has a ' ' at the end, so the shortest segment in the string is "* ", which is 2 chars long.
The c in your loop is the index of the char array that this iteration should write to, the a is the index inside the current group of '*'s, and b is length of the current group of '*'s less one (since we want to count the spaces). Directly before the if clause in your for loop, it can be said that c is the sum from 2 to b plus a.
In other words, if a=0, and b=1, then c=0, because the sum from 2 to 0 is 0, plus 0 is 0.
If a=3, and b=4, then c= (2+3+4) + 3 = 12.
This means that you could write your code like this:
#include <stdio.h>
const int LENGTH = 20;
int sumFromTwo(int in){ //Recursive function to calculate sigma(2:in)
if(in < 2)
return 0;
else
return in + sumFromTwo(in - 1);
}
int main()
{
char arr[LENGTH + 1]; //Extra byte for null-terminator
for (int a = 0, b = 1; sumFromTwo(b) + a < LENGTH ; ) {
if (a < b) {
arr[sumFromTwo(b) + a] = '*';
a++;
} else {
arr[sumFromTwo(b) + a] = ' ';
a = 0;
b++;
}
}
arr[LENGTH] = '\0'; //Always null-terminate your strings
printf(arr);
return EXIT_SUCCESS;
}
But using recursion to avoid using a variable that is almost certainly going to be optimized into a register anyway is not going to save your computer any resources, least of all RAM, so it is definitely cleaner to do it the way you did in your question (but please null-terminate your string before passing it to your choice of printf or puts).
I have a string given (a+b)&(a+c) and I have created a truth table with values of a,b, and c. Now the problem is to evaluate the logic expression by substituting a,b, and c with corresponding values from the truth table. How it can be done in C?
Ex: a=0 b=0 c=0 r=(0+0)&(0+)=0
a=0 b=0 c=1 r=(0+0)&(0+1)=0
and so on
The code itself looks like this
#include <stdio.h>
#include <stdlib.h>
int main()
{
char c,* str, *vars, **result;
int i=0,count=0,j=0;
unsigned long long rows;
str = (char*) malloc(1*sizeof(char));
vars=(char*) malloc(1*sizeof(char));
result=(char**)malloc(1*sizeof(char));
char values[] = {'F', 'T'};
while ((c = getchar()) != EOF)
{
str[i++] = c;
str = (char*) realloc(str, (i+1) * sizeof(char));
if (c >= 'a' && c <= 'z')
{
vars[j++]=c;
vars=(char*) realloc(vars,(j+1)*sizeof(char));
count++;
}
}
rows=1ULL<<(count);
result=(char**)realloc(result,(rows+2)*sizeof(char));
for (i = 0; i < rows+1; i++)
{
result[i]=(char*)malloc(sizeof(char)*(count+1));
for (j = 0; j < count; j++)
{
if(i==0)
result[i][j]=vars[j];
else
result[i][j]=values[(i >> j) & 1];
}
}
result[0][count]='R';
for(i=0;i<rows+1;i++)
{
for(j=0;j<count+1;j++)
{
//do something
}
}
Now the problem is to evaluate the logic expression by substituting a,b, and c with corresponding values from the truth table.
Aside from the issues mentioned in the question's comments, substituting alone won't do the job to evaluate the logic expression. The following function for example substitutes the values while evaluating the expression. (You didn't specify the general syntax of your expressions, so I chose to support combinations of the used operators and lower case variables.)
#include <ctype.h>
#include <string.h>
int indx(char *s, char c) { return strchr(s, c)-s; }
char *gstr, *gvars, *vals; // expression string, variables, value combination
char eval()
{ // evaluate expression "gstr"
char or = 0; // neutral element of +
do
{
char and = 1; // neutral element of &
do
{
char c = *gstr++; // get next token
if (islower(c))
and &= indx("FT", vals[indx(gvars, c)]);
else
if (c == '(')
{ // evaluate subexpression
and &= eval();
c = *gstr++; // get next token
if (c != ')')
printf("error at '%c': expected ')'\n", c), exit(1);
}
else
printf("error at '%c'\n", c), exit(1);
} while (*gstr == '&' && ++gstr);
or |= and;
} while (*gstr == '+' && ++gstr);
return or;
}
It can be called from your main (inserted in your code, hence the inconsistent spacing)
result[0][count]='R';
gvars = vars; // make variable names globally accessible
for (i = 1; i <= rows; ++i)
{
gstr = str, vals = result[i], // globally accessible
result[i][count] = values[eval()];
while (isspace(*gstr)) ++gstr;
if (*gstr)
printf("error at '%c': expected end of input\n", *gstr), exit(1);
}
for(i=0;i<rows+1;i++)
{
for(j=0;j<count+1;j++)
{
putchar(result[i][j]);
}
putchar('\n');
}
(Don't forget to put str[i] = '\0'; after your getchar loop to make a null-terminated string.) Note that due to the given for loop counting, the order of the truth table entries is somewhat unusual in that the row with all variables F comes last.
I'm Programming in C, using Linux GCC Compiler. I'm very much new to programming.
I'm confused as to why my in[] char array would be changed at all in the function. Doesn't the code simply count the amount of subscripts in in[] and then copy its contents into out[] but backwards? How is it being changed in the function?
/*reverse in to out*/
void reverse(char in[], char out[]) {
int i, l,b;
b = i = l = 0;
while (in[i] != '\0')
++i;
for(l=i;l > 0; l--) {
in[l] = out[b];
++b;
}
return;
}
Your assignment statement is backwards.
in[l] = out[b];
Means "Assign the value in array out at index b to array in index l". This line should instead be
out[b] = in[l];
And BTW, you don't need an empty return statement, you can simply omit this in a void function.
for(l=i-1;l >= 0; l--) {
out[b] = in[l];
++b;
}
out[b] = '\0';
Four problems fixed: start at i-1, test for l>=0, reverse the assignment, and terminate out with a null character.
Also, a good idea is to use const when a function argument will not be changed. In this case, const char in[] would let you spot the assignment error because the compiler would give you a compile time error.
You can use strlen :
for(l=strlen(in), b=0; l>=0; l--)
out[b++] = in[l];
// ensure null terminated so strlen out works
out[b] = '\0';
This assumes out is wide enough for in AND in is null terminated
This is a function i made to count number of zeroes at the end of the factorial of a number b recursively.
However i'm getting runtime error due to the used code.Pardon my naivety but any help in this would be appreciated.
int noz(int b)
{
int c=0;
int e = b;
if(e < 5)
return 0;
while(e > 0)
c = c + (e/5) + noz(e/5);
return c;
}
You are encountering "runtime error" because:
int c;
...
while(e > 0)
c = c + (e/5) + noz(e/5); // <-- HERE
you are using uninitialized local variable c, which produces undefined behavior.
You could zero-initialize this variable to prevent it happen:
int c = 0;
And also note that in case that argument of your function is greater or equal than 5, this function doesn't return anything (thanks to #Paul R for pointing this out) and another problem is that you have loop with the condition e > 0 but the loop doesn't change the value of e making it infinite loop.
Your function could look like this instead (I'm not sure what exactly is the desired logic here):
int noz(int b)
{
int c = 0;
if (b < 5)
return 0;
else
return c + (b/5) + noz(b/5);
}
//count n! tail zero
int noz(int n){
int count;
if(n < 5) return 0;
count = n / 5;
return count + noz(count);
}
I'm trying to write a program in C that converts hexadecimal numbers to integers. I've written successfully a program that converts octals to integers. However, the problems begin once I start using the letters (a-f). My idea for the program is ads follows:
The parameter must be a string that starts with 0x or 0X.
The parameter hexadecimal number is stored in a char string s[].
The integer n is initialized to 0 and then converted as per the rules.
My code is as follows (I've only read up to p37 of K & R so don't know much about pointers) :
/*Write a function htoi(s), which converts a string of hexadecimal digits (including an optional 0x or 0X) into its equivalent integer value. The allowable digits are 0 through 9, a through f, and A through F.*/
#include <stdio.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
int htoi(const char s[]) { //why do I need this to be constant??
int i;
int n = 0;
int l = strlen(s);
while (s[i] != '\0') {
if ((s[0] == '0' && s[1] == 'X') || (s[0] == '0' && s[1] == 'x')) {
for (i = 2; i < (l - 1); ++i) {
if (isdigit(s[i])) {
n += (s[i] - '0') * pow(16, l - i - 1);
} else if ((s[i] == 'a') || (s[i] == 'A')) {
n += 10 * pow(16, l - i - 1);
} else if ((s[i] == 'b') || (s[i] == 'B')) {
n += 11 * pow(16, l - i - 1);
} else if ((s[i] == 'c') || (s[i] == 'C')) {
n += 12 * pow(16, l - i - 1);
} else if ((s[i] == 'd') || (s[i] == 'D')) {
n += 13 * pow(16, l - i - 1);
} else if ((s[i] == 'e') || (s[i] == 'E')) {
n += 14 * pow(16, l - i - 1);
} else if ((s[i] == 'f') || (s[i] == 'F')) {
n += 15 * pow(16, l - i - 1);
} else {
;
}
}
}
}
return n;
}
int main(void) {
int a = htoi("0x66");
printf("%d\n", a);
int b = htoi("0x5A55");
printf("%d\n", b);
int c = htoi("0x1CA");
printf("%d\n", c);
int d = htoi("0x1ca");
printf("%d\n", d);
}
My questions are:
1. If I don't use const in the argument for htoi(s), i get the following warnings from the g++ compiler :
2-3.c: In function ‘int main()’: 2-3.c:93:20: warning: deprecated
conversion from string constant to ‘char*’ [-Wwrite-strings]
2-3.c:97:22: warning: deprecated conversion from string constant to
‘char*’ [-Wwrite-strings] 2-3.c:101:21: warning: deprecated conversion
from string constant to ‘char*’ [-Wwrite-strings] 2-3.c:105:21:
warning: deprecated conversion from string constant to ‘char*’
[-Wwrite-strings]
Why is this?
2.Why is my program taking so much time to run? I haven't seen the results yet.
3.Why is it that when I type in cc 2-3.c instead of g++ 2-3.c in the terminal, I get the following error message:
"undefined reference to `pow'"
on every line that I've used the power function?
4. Please do point out other errors/ potential improvements in my program.
If I don't use const in the argument for htoi(s), i get the following warnings from the g++ compiler
The const parameter should be there, because it is regarded as good and proper programming to never typecast away const from a pointer. String literals "..." should be treated as constants, so if you don't have const as parameter, the compiler thinks you are casting away the const qualifier.
Furthermore, you should declare all pointer parameters that you don't intend to modify the contents of as const, Google the term const correctness.
Why is my program taking so much time to run? I haven't seen the results yet.
I think mainly because you have made an initialization goof-up. int i; i contains rubbish. Then while (s[rubbish_value] != '\0'). This function can be written a whole lot better too. Start by checking for the 0x in the start of the string, if they aren't there, signal some error (return NULL?), otherwise discard them. Then start one single loop after that, you don't need 2 loops.
Note that the pow() function deals with float numbers, which will make your program a slight bit slower. You could consider using an integer-only version. Unfortunately there is no such function in standard C, so you will have to found one elsewhere.
Also consider the function isxdigit(), a standard function in ctype.h, which checks for digits 0-9 as well as hex letters A-F or a-f. It may however not help with performance, as you will need to perform different calculations for digits and letters.
For what it is worth, here is a snippet showing how you can convert a single char to a hexadecimal int. It is not the most optimized version possible, but it takes advantage of available standard functions, for increased readability and portability:
#include <ctype.h>
uint8_t hexchar_to_int (char ch)
{
uint8_t result;
if(isdigit(ch))
{
result = ch - '0';
}
else if (isxdigit(ch))
{
result = toupper(ch) - 'A' + 0xA;
}
else
{
// error
}
return result;
}
Don't use a C++ compiler to compile a C program. That's my first advice to you.
Secondly const in a function parameter for a char * ensures that the programmer doesn't accidentally modify the string.
Thirdly you need to include the math library with -lm as stated above.
a const char[] means that you cannot change it in the function. Casting from a const to not-const gives a warning. There is much to be said about const. Check out its Wikipedia page.
--
Probably, cc doesn't link the right libraries. Try the following build command: cc 2-3.c -lm
Improvements:
Don't use pow(), it is quite expensive in terms of processing time.
Use the same trick with the letters as you do with the numbers to get the value, instead of using fixed 'magic' numbers.
You don't need the last else part. Just leave it empty (or put an error message there, because those characters aren't allowed).
Good luck!
About my remark about the pow() call (with the use of the hexchar_to_int() function described above, this is how I'd implement this (without error checking):
const char *t = "0x12ab";
int i = 0, n = 0;
int result = 0;
for (i = 2; i < strlen(t); i++) {
n = hexchar_to_int(t[i]);
result |= n;
result <<= 4;
}
/* undo the last shift */
result >>= 4;
I just worked through this exercise myself, and I think one of the main ideas was to use the knowledge that chars can be compared as integers (they talk about this in chapter 2).
Here's my function for reference. Thought it may be useful as the book doesn't contain answers to exercises.
int htoi(char s[]) {
int i = 0;
if(s[i] == '0') {
++i;
if(s[i] == 'x' || s[i] == 'X') {
++i;
}
}
int val = 0;
while (s[i] != '\0') {
val = 16 * val;
if (s[i] >= '0' && s[i] <= '9')
val += (s[i] - '0');
else if (s[i] >= 'A' && s[i] <= 'F')
val += (s[i] - 'A') + 10;
else if (s[i] >= 'a' && s[i] <= 'f')
val += (s[i] - 'a') + 10;
else {
printf("Error: number supplied not valid hexadecimal.\n");
return -1;
}
++i;
}
return val;
}
Always init your variables int i=0, otherwise i will contain a garbage value, could be any number, not necessary 0 as you expect. You're running the while statement in an infinite loop, that's why it takes forever to get the results, print i to see why. Also, add a break if the string doesn't start with 0x, will avoid the same loop issue when the user is used on a random string. As others mention you need to import the library containing pow function and declare your string with const to get rid of the warning.
This is my version of program for the question above. It converts the string of hex into decimal digits irrespective of optional prefix(0x or 0X).
4 important library functions used are strlen(s), isdigit(c), isupper(c), isxdigit(c), pow(m,n)
Suggestions to improve the code are welcome :)
/*Program - 5d Function that converts hex(s)into dec -*/
#include<stdio.h>
#include<stdlib.h>
#include<math.h> //Declares mathematical functions and macros
#include<string.h> //Refer appendix in Page 249 (very useful)
#define HEX_LIMIT 10
int hex_to_dec(char hex[]) //Function created by me :)
{
int dec = 0; //Initialization of decimal value
int size = strlen(hex); //To find the size of hex array
int temp = size-1 ; //Pointer pointing the right element in array
int loop_limit = 0; //To exclude '0x' or 'OX' prefix in input
if(hex[0]=='0' && ((hex[1]=='x') || (hex[1]=='X')))
loop_limit = 2;
while(temp>=loop_limit)
{
int hex_value = 0; //Temporary value to hold the equivalent hex digit in decimal
if(isdigit(hex[temp]))
hex_value = (hex[(temp)]-'0') ;
else if(isxdigit(hex[temp]))
hex_value = (toupper(hex[temp])-'A' + 10);
else{
printf("Error: No supplied is not a valid hex\n\n");
return -1;
}
dec += hex_value * pow(16,(size-temp-1)); //Computes equivalent dec from hex
temp--; //Moves the pointer to the left of the array
}
return dec;
}
int main()
{
char hex[HEX_LIMIT];
printf("Enter the hex no you want to convert: ");
scanf("%s",hex);
printf("Converted no in decimal: %d\n", hex_to_dec(hex));
return 0;
}