Just started learning c. I'm confused with the pointers and arrays.
This is my main function.
int next_statement(char *a, int n);
void consume_char(char c);
int var_lib_check(char type,char var);
int
main(int argc, char *argv[]) {
char statement[MAX_LINE];
int statement_len;
char type[MAX_LINE];
char var[MAX_LINE];
/* Print the output header comment */
printf(OUTPUT_HEADER, argv[0]);
/* Loop through statements read on stdin */
while ((statement_len = next_statement(statement,MAX_LINE)) > 0) {
printf("%s\n",statement);
sscanf(statement,"%s %s",type,var);
var_lib_check(*type,*var);
}
return 0;
int
var_lib_check(char type,char var){
char var_library[MAX_VARS][MAX_LINE];
char new_var[MAX_LINE];
int num_of_var;
int z;
num_of_var = 0;
printf("%s and %s",&type,&var);
if (strcmp(&type,DOUBLE_TYPE)==0||strcmp(&type,INT_TYPE)==0||
strcmp(&type,RTRN_TYPE)==0){
for (z= 0; z < num_of_var; z++){
if (strcmp(var_library[z],&var) == 0){
sprintf(new_var,"x%d",z);
printf("%s %s",&type,new_var);
return z;
}
}
strcpy(var_library[num_of_var],&var);
num_of_var += 1;
sprintf(new_var,"%x%d",num_of_var);
printf("%s %s",&type,new_var);
}
return num_of_var;
}
This program reads the input and if it is either int or double ... it would replace it to be for e.g. int x0.
Why does it only print the first letter of the type and variable when it runs the function when it should print the whole string?
int
next_statement(char *a, int n) {
int c, i;
for (i=0; i < n && (c = getchar()) != EOF; i++) {
if (c == CHAR_SEMI) {
consume_char('\n');
break;
}
a[i] = c;
}
if (c == CHAR_SEMI) {
a[i] = '\0';
return i; /* index when ; was read, so the length of saved. */
}
else if (i >= n) {
printf("%s Line too long.\n", ERROR_PREFIX);
exit(EXIT_FAILURE);
}
return 0;
}
/* reads one char from stdin and errors if it is not what was
* expected, thereby "consuming" the given char.
*/
void
consume_char(char c) {
int x;
if ((x=getchar()) != c) {
printf("%s expected '%c' found '%c'.\n", ERROR_PREFIX, c, x);
exit(EXIT_FAILURE);
}
return;
You have the function definition as
int var_lib_check(char type,char var){
and you call it as
var_lib_check(*type,*var);
By doing this, you are only passing one character, and not the entire string to it.
You should change your function to
int var_lib_check(char *type,char *var)
and call it as
var_lib_check(type,var);
Now, you are passing the string to it, and you can work on it like a pointer.
It's because you are passing only the first char to var_lib_check(). You have to pass the array, so first fix this
var_lib_check(*type,*var);
make it
var_lib_check(type,var);
then fix the var_lib_check() function
int
var_lib_check(char *type, char *var)
{
char var_library[MAX_VARS][MAX_LINE];
char new_var[MAX_LINE];
int num_of_var;
int z;
num_of_var = 0;
printf("%s and %s", type, var); /* remove the & */
if (strcmp(type, DOUBLE_TYPE) == 0 || strcmp(type, INT_TYPE) == 0 || \
strcmp(type, RTRN_TYPE)==0)
{
for (z = 0 ; z < num_of_var ; z++)
{
if (strcmp(var_library[z], var) == 0)
{
sprintf(new_var, "x%d", z);
printf("%s %s", type, new_var);
return z;
}
}
strcpy(var_library[num_of_var], var);
num_of_var += 1;
sprintf(new_var, "%x%d", num_of_var);
printf("%s %s", type, new_var);
}
return num_of_var;
}
Most of the code invokes undefined behavior, because you pass the address to a char where a pointer to a string is expected.
A string consists of a sequence of non-nul bytes followed by a nul byte, since you where passing the address to just one byte, the functions, namely printf() and strcmp() where reading past the value of the passed variable.
Related
I want to make a program, which prints the number of smallest length of string. I have a file of words, which I open from stdin and save it to buffer.
My code so far prints the length of each word. But I can't figure out how to compare these numbers.
For example in file are:
Hello
Hi
My program does:
6
3
The output should be:
3
I can't figure ou how to continue. Do you have any advice?
#include <stdio.h>
int min_stat(char str[])
{
int min=0;
for(int i=0; str[i] != '\0'; i++)
{
min++;
}
return min;
}
int main(int argc, char *argv[])
{
if(argc < 1){
fprintf(stderr,"Error\n");
return 1;
}
char param = argv[1][0];
int val=100;
char buffer[val];
if(param == '1')
{
while(fgets(buffer, val, stdin) != NULL)
{
int a = min_stat(buffer);
printf("%d\n", a);
}
}
return 0;
}
You need to save the minimum lenght of the string somewhere and update it if a shorter string is detected. Your min_stat function returns the number of characters of the string.
I would use something like this:
#define MAX_LENGHT 1000
int main(int argc, char *argv[])
{
if(argc < 1){
fprintf(stderr,"Error\n");
return 1;
}
char param = argv[1][0];
int val=100;
char buffer[val];
/* the maximum possible lenght */
int min_lenght = MAX_LENGHT;
if(param == '1')
{
while(fgets(buffer, val, stdin) != NULL)
{
int a = min_stat(buffer);
/* update the mimimum lenght if it is smaller
than the current value */
if (a < min_lenght) {
min_lenght = a;
}
printf("%d\n", a);
}
}
/* print the minimum lenght */
printf("Minimum: %d\n", min_lenght);
return 0;
}
You should not use a variable to initialize the char array, because you are using Variable Lenght Arrays (VLA) and not static arrays. If you are learning c you should use static arrays and so:
char buffer[MAX_LENGHT];
where MAX_LENGHT is a constant or a pre-processor definition.
I have to make a program in which I have to add the result of x dices with n faces plus or minus a constant(C). The input should be a string like this: "xDn+-C" (x, n and C must be a decimal number). For example: "4D5+6" or "6D9-5". The D just means "Dice".
I used a function to randomize the rolls but I don't know how to continue...
void initD6(void) {
srand((unsigned)time( NULL ) );
}
int D6(void) {
return ((rand()%6)+1);
}
int main(){
char Dice[4];
for(i=0; i<5; i++){
Dice[i] = D6();
return 0;
}
I don't know how should I take that input as a string and the adding or substracting, and also don't know what should I do next.
Add a struct:
struct rules
{
int dices;
int facesPerDice;
int offset;
};
Solve the dice problem:
int throwDice(int faces)
{
return (rand() % faces) + 1;
}
int playGame(struct rules rules)
{
int result = 0;
for (int i = 0; i < rules.dices; i++)
result += throwDice(rules.facesPerDice);
return result + rules.offset;
}
Solve the parsing problem:
/**
Converts a string to a unsigned int until an invalid character is found or a null character is found.
You should replace this with the function you normally use to convert a string to a integer.
*/
unsigned int stringToUInt(char *str)
{
unsigned int result = 0;
int charindex = 0;
char currentchar;
while ((currentchar = str[charindex++]) != '\0')
{
if (currentchar < '0' || currentchar > '9')
break;
result *= 10;
result += currentchar - '0';
}
return result;
}
/**
Reads a string and generates a struct rules based on it.
The string is expected to be given in the following format:
[uint]'D'[uint]['+' or '-'][uint]
where:
the first uint is the number of dices to roll
the second uint is the number of faces per dice
the third uint is the offset
Terminates the program if something goes wrong.
*/
struct rules parse(char *str)
{
struct rules result;
result.dices = stringToUInt(str);
while (*(str++) != 'D')
if (*str == '\0')
exit(1);
result.facesPerDice = stringToUInt(str);
while (*(str++) != '+' && *(str-1) != '-')
if (*str == '\0')
exit(1);
result.offset = stringToUInt(str);
result.offset *= (*(str-1) == '+' ? 1 : -1);
return result;
}
Put everything together:
int main(int argc, char *argv[])
{
srand(time(NULL));
char input[] = "3D6+9"; //You could use console input if you want
struct rules rules = parse(input);
int gameResult = playGame(rules);
printf("Game result: %d\n", gameResult);
return 0;
}
Assuming no errors in the input, a function which solves your task is:
int throw_dice(const char* s)
{
int num, sides, res;
sscanf(s,"%iD%i%i", &num, &sides, &res);
for (int i = 0; i < num; ++i) {
res += rand() % sides + 1;
}
return res;
}
For simple string parsing sscanf() is a pretty good function. For more complex tasks it's better to use a regular expression library.
As usual, don't relay on rand() for anything but the most simple dice games, with no money involved.
You can try it with the following full example:
#include <stdio.h>
int throw_dice(const char* s)
{
int num, sides, res;
sscanf(s,"%iD%i%i", &num, &sides, &res);
for (int i = 0; i < num; ++i) {
res += rand() % sides + 1;
}
return res;
}
void throw_multiple_times(const char* s, int times)
{
printf("%s: ", s);
for (int i = 0; i < times; ++i) {
printf("%i ", throw_dice(s));
}
printf("\n");
}
int main(void)
{
srand((unsigned)time(NULL));
const char* s;
throw_multiple_times("4D5+6", 100);
throw_multiple_times("6D9-5", 100);
return 0;
}
Test it here.
This question already has answers here:
Why is 49, 50, 51, 52 stored in the array when I declare testArray[] = {'1','2','3','4','5'}? (C programming)
(5 answers)
Convert a character digit to the corresponding integer in C
(14 answers)
Closed 4 years ago.
My code takes in 1 command line argument which reads the command line character by character and places the stack accordingly.
command line argument of: "12+" should equal to equation of "1+2"
int pop(stack *p);
int main(int argc, char **argv)
{
stack ph;
int i, a, b;
int val = 0;
if (argc!=2)
{
printf("Usage: %s argument\n", argv[0]);
exit(1);
}
else{
int i;
int length = strlen(argv[1]);
int count;
initializedStack(&ph);
for(i=0;i<length;i++)
{
if (argv[1][i] == '+'){
a = pop(&ph);
printf("%d\n", a);
b = pop(&ph);
printf("%d\n", b);
val = a+b;
push(&ph,val);
}
else{
push(&ph, argv[1][i]);
}
}
printf("%d\n", pop(&ph));
}
return 0;
}
void initializedStack(stack *p){
p->top = 0;
}
void push(stack *p, int val){
p->top++;
p->items[p->top] = val;
}
int pop(stack *p){
int y;
y = p->items[p->top];
p->items[p->top] = 0;
(p->top)--;
return y;
}
I am currently in the testing stages of the program and it only includes the addition operation. To test this program out, I have print statements for the addition part of the if statements and pop at the end. Running this gives me the output of:
50
49
99
When the output should be:
1
2
3
It seems like the addition operation works, but I do not know where the 50 and 49 is coming from? What is correct way to write my code so that it provides the accurate output? Thanks!
When you do:
push(&ph, argv[1][i]);
You are pushing the ASCII value for a given digit and not its decoded numeric value [the latter is equivalent to what atoi would return, if it could operate on a single character].
This is probably not what you, given that later, you push a + b, which are numeric/binary values.
Although this works for a single digit only, the quick fix is:
push(&ph, argv[1][i] - '0');
Otherwise, in general, you'll need to assemble the entire digit string and decode it with (e.g.) atoi.
In that case, you'd need to handle some whitespace for something 12 23 +
Here is a cleaned up version that uses strtok and atoi to allow more general numbers. [please pardon the gratuitous style cleanup]:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct {
int top;
int items[100];
} stack;
void
initializedStack(stack *p)
{
p->top = 0;
}
void
push(stack *p, int val)
{
p->top++;
p->items[p->top] = val;
}
int
pop(stack *p)
{
int y;
y = p->items[p->top];
p->items[p->top] = 0;
(p->top)--;
return y;
}
int
main(int argc, char **argv)
{
stack ph;
int i,
a,
b;
int val = 0;
char *buf;
char *token;
int chr;
if (argc != 2) {
printf("Usage: %s argument\n", argv[0]);
exit(1);
}
buf = argv[1];
initializedStack(&ph);
while (1) {
token = strtok(buf," ");
if (token == NULL)
break;
buf = NULL;
chr = token[0];
if (strcmp(token,"+") == 0) {
a = pop(&ph);
printf("%d\n", a);
b = pop(&ph);
printf("%d\n", b);
val = a + b;
push(&ph, val);
continue;
}
if ((chr >= '0') && (chr <= '9')) {
val = atoi(token);
push(&ph, val);
continue;
}
}
printf("%d\n", pop(&ph));
return 0;
}
int findChar(char * str, char c);
Searches for the character c in the string str and returns the index of the character in the string. If the character does not exist, returns -1
int replaceChar(char * str, char c1, char c2);
Searches for the character c1 in the string str and if found, replace it with c2.The
function returns the number of replacements it has performed. If the character does not
exist, returns 0.
int removeChar(char * str1, char * str2, char c);
Creates a copy of str1 into str2 except for the character c that should be replaced
with ‘*’
Hi guys So Far I have the following Code Which is not optimal. I have been trying to debug this for a bit and finally have come here for help.
findChar(char *str, char c);
replaceChar(char *str, char c1, char c2);
int main(){
char str[] ="all";
if (findChar(str, 'l'))
printf("Character found at index: %d\n", findChar(str, 'l'));
else
printf("No Character found\n");
if (replaceChar(str, 'x', 'a') !=0){
printf("%d",replaceChar(str,'x','a'));
printf("\n");
}
else
printf("Character does not exist\n");
system("pause");
return 0;
}
int findChar(char *str, char c){
for (int i = 0; i <strlen(str); i++){
if (str[i] == c)
return i;
}
return -1;
}
int replaceChar(char *str, char c1, char c2){
int position = 0;
int count = 0;
do{
int position = findChar(str, c1);
if (position != -1){
str[position] = c2;
count++;
}
} while (findChar(str, c1) != -1);
if (count == 0){
return 0;
}
else{
return count;
}
}
In replaceChar, anytime you call findChar(str, c1) it will always return the same value, since findChar grabs the first instance of c1 in str. So position is always the same and your loop condition is always the same.
Rather than having replaceChar call findChar, it should just loop through the string itself. Much simpler logic that way.
int replaceChar(char *str, char c1, char c2){
int i;
int count = 0;
int len = strlen(str);
for (i=0; i<len; i++) {
if (str[i] == c1) {
str[i] = c2;
count++;
}
}
return count;
}
I'm trying to write a recursive algorithm that obtains to count specified a letter by user. But, I'm stuck in two cases. First, I think I must get 2 as result, I can't. Second, If there is no limit key, for instance the limit character specified as z by user , how the characters can be scanned up to end character here g ? The problem little bit complicated for me. I need your advices and ideas. Thank you all appreciated answers.
example string is: how are you i am testing
another examples:
#include <stdio.h>
int lettercount(char* str, char key, char limit);
int main(){
char test[]="how are you i am testing";
int num;
num=lettercount(test,'a','t');
printf("%d",num);
return 0;
}
int lettercount(char* str, char key, char limit)
{
int count = 0;
if(str[0] == limit)
{
return 0;
}
else if(str[0] == key)
{
lettercount(&str[1], key, limit);
count++;
}
else
lettercount(&str[1], key, limit);
return count;
}
as the code is unwinding from the recursion(s)
it needs to accumulate the count
the following code should work for your needs.
Note: this returns 0 if key and limit are the same char
int lettercount(char* str, char key, char limit)
{
int count = 0;
if(str[0] == limit)
{
return 0;
}
// implied else, more char in string to check
if(str[0] == key)
{
count++;
}
count += lettercount(&str[1], key, limit);
return count;
} // end function: lettercount
With a recursive function, you need 3 things. (1) set up in the function that prepares for the next call; (2) a recursive call; and (3) a way to terminate the recursion. Here is one approach. Note: the version in the code below is a long version for readability, a short version is included at the end:
#include <stdio.h>
/* recursively find the number of occurrences
of 'c' in 's' (n is provided as '0')
*/
int countchar (char *s, char c, int n)
{
char *p = s;
if (!*p)
return n;
if (*p == c)
n = countchar (p+1, c, n+1);
else
n = countchar (p+1, c, n);
return n;
}
int main (int argc, char **argv) {
if (argc < 3) {
fprintf (stderr, "\n error: insufficient input. Usage: %s <string> <char>\n\n", argv[0]);
return 1;
}
int count = countchar (argv[1], *argv[2], 0);
printf ("\n There are '%d' '%c's in: %s\n\n", count, *argv[2], argv[1]);
return 0;
}
output:
$ ./bin/rec_c_in_s "strings of s'es for summing" s
There are '5' 's's in: strings of s'es for summing
You can make the function shorter, but slightly less readable with:
int countchar (char *s, char c, int n)
{
char *p = s;
if (!*p) return n;
return countchar (p+1, c, (*p == c) ? n+1 : n);
}