Hello guys please help me to understand something !
I have a txt file and I read different values. I'm doing it successfully but I have an ASCII too, ie. KS98B2
I am trying to read it and store it in a value. Could you please have a look at my code? The word "KS98B2" should be stored at the variable "name". So I declare it in the main as a char. Do you agree?
Inside the "asc" function there is a putchar, and it is printed properly, I checked that, I receive KS98B2.
But, inside the asc function printf gives the value : 84122658
And inside main printf gives the value: 24
Yes, I put %d in printf and name is a char, but how is it possible that the variable is not the same ? How can I make it work? Please help me !
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
FILE *file;
char ch;
int asc(char eow, bool *eof) {
int var = 0;
while((ch=fgetc(file))!=EOF) {
putchar(ch);
if ((ch >= 'A') && (ch <= 'Z')) {
var <<= 4;
var += (ch - 'A' + 65);
}
else if ((ch >= '0') && (ch <= '9')) {
var <<= 4;
var += (ch - '0');
} else if (ch == eow) {
return var;
} else {
puts("Incorrect syntax.\n");
}
}
putchar('\n');
printf("Var inside asc %d\n", var);
}
int main() {
char name;
bool eof = false;
if ((file = fopen("messages.txt", "r")) == NULL) {
puts("WRONG FILE\n");
return 1;
}
while(!feof(file)) {
name= asc('\n', &eof);
printf("Var main: %d\n", name);
}
fclose(file);
return 0;
}
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
FILE *file;
//char ch;//There is no need to be a global variable
int asc(char eow, bool *eof) {
int var = 0;
int ch;//Type in order to compare the EOF and value must be int
while((ch=fgetc(file))!=EOF) {
if(isupper(ch))
var = var * 36 + (ch - 'A' + 10);
else if(isdigit(ch))
var = var * 36 + (ch - '0');
else if (ch == eow)
return var;
else {
fprintf(stderr, "\nIncorrect syntax.\n");
}
}
*eof = true;
return var;
}
int main(void) {
int name;//It must be int to receive the value of int
bool eof = false;
if ((file = fopen("messages.txt", "r")) == NULL) {
puts("WRONG FILE\n");
return 1;
}
while(!feof(file)) {
name= asc('\n', &eof);
printf("Var main: %d\n", name);
}
fclose(file);
return 0;
}
void putdecimal(int name) {
int i=0;
int var = name;
int array[30];
int cnt = 0;
while(var){
array[cnt++] = var % 36;
var /= 36;
}
for(i = cnt-1; i>=0; i--){
if(array[i]<10)
putchar(array[i] + '0');
else
putchar(array[i] - 10 + 'A');
}
}
Example to store the read characters into an array.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
FILE *file;
char *gasc(int size, char buff[size], char eow){
int i = 0, ch = 0;
while(i < size - 1 && (ch=fgetc(file))!=EOF && ch != eow){
if (isupper(ch) || isdigit(ch)){
buff[i++] = ch;
} else {
fprintf(stderr, "\nIncorrect syntax.\n");
}
}
buff[i] = '\0';
if(i == 0 && ch == EOF)
return NULL;
return buff;
}
int main(void) {
char name[20];
if ((file = fopen("messages.txt", "r")) == NULL) {
puts("WRONG FILE\n");
return 1;
}
//is_eof is no longer necessary to represent NULL return value of gasc instead of EOF.
while(gasc(sizeof(name), name, '\n') != NULL) {
printf("'%s'\n", name);
}
fclose(file);
return 0;
}
Related
Is there more elegant way to do this task?
Program asks user for integer and repeats if non-digital characters are entered.
To exit loop two conditions expected:
a) all entered characters are digits
b) last character is '\n'
Short solutions like scanf don’t work properly, other approaches require lots of variables loops and if else conditions. User input is common task and I would like to have proper reusable template.
Subjective opinions are appreciated. Way to simplify this function or advice on another solution. Improve formatting. Reading for more systematic understanding.
#include <stdio.h>
int getIntOnly();
int main() {
int x = 0;
x = getIntOnly();
printf("\nvalue entered is: %d \n", x);
}
int getIntOnly() {
int ch, num, quit, abc;
do {
num = 0;
ch = 0;
quit = 0;
abc = 0;
printf("Enter the input: ");
do {
ch = getchar();
if (ch >= 48 && ch <= 57) {
num = num * 10 + (ch - 48);
}
else if (ch == '\n') {
quit = 1;
}
else {
abc = 1;
}
}
while (quit == 0);
}
while (quit == 0 || abc == 1);
return (num);
}
Using fgets() means you'll get the full text at once.
You can then examine it (and convert it too) to suit your needs.
int getIntOnly( void ) {
int value = 0, i = 0;
char buf[ 64 ];
do {
printf( "Enter integer value: " );
fgets( buf, sizeof( buf ), stdin );
value = 0;
for( i = 0; '0' <= buf[i] && buf[i] <= '9'; i++ )
value = value * 10 + buf[i] - '0';
} while( buf[i] != '\n' ); // good! reached end of line
return value;
}
May be better? Add some validity checks for the result of fgets() and strtol() according to your original code.
#include <stdio.h>
#include <limits.h>
#include <stdbool.h>
#include <stdlib.h>
int getIntOnly();
int main() {
int x = 0;
x = getIntOnly();
printf("\nvalue entered is: %d \n", x);
}
bool isDigit(char ch) {
return (ch >= '0' && ch <= '9')? true : false;
}
bool isAllDigit(char *buf) {
int i;
for (i = 0; buf[i] != '\n'; i++) {
if (isDigit(buf[i]) == false) {
return false;
}
}
return true;
}
bool isVaildInt(long int number) {
return (number >= INT_MIN && number <= INT_MAX)? true : false;
}
int getIntOnly() {
char buf[100];
long int num;
bool done = false;
do {
/* read line-by-line */
fgets(buf, 100, stdin);
if (isAllDigit(buf) == false)
continue;
num = strtol(buf, NULL, 10);
/* strtol() returns long int */
if (isVaildInt(num) == false)
continue;
done = true;
} while (done == false);
return num;
}
I'm stuck on an assignment I have to read from console really long number and then print it out using char* arr. Then I need to add and subtract number 1 array to number2 array. To be honest adding and subtracting I will probably deal on my own but I cannot figure out how to read those input characters, character by character and make while break after enter in console.
My code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int subtract(const char* number1, const char* number2, char** result){
if(number1 == NULL || number2 == NULL){
return 1;
}
return 0;
}
int add(const char* number1, const char* number2, char** result) {
if(number1 == NULL || number2 == NULL){
return 1;
}
return 0;
}
int input_check(int check, char* number) {
if (check != 1) {
return 1;
}
else {
return 0;
}
}
int main()
{
char* number1;
//char* number2;
//char** result;
int check = 0;
number1 = (char*)calloc(200,sizeof(char));
//number2 = (char*)calloc(200, sizeof(char));
//result = (char*)malloc(sizeof(char) * sizeof(char) * 400);
if (number1 == NULL) {
printf("Failed to allocate memory");
return 8;
}
printf("Input first num: ");
int i = 0;
while (1) {
char retVal;
scanf("%c", &retVal);
if (retVal >= 48 || retVal <= 57 || retVal != '\0') {
*(number1 + i) = retVal;
if ((number1 + i) == NULL) {
break;
}
printf("%d", atoi((number1 + i)));
i++;
}
else
{
break;
}
}
return 0;
}
Thanks for any help
As there is no limit on the numbers, you need to use dynamic memory allocation.
The straightforward (brute-force) way is to keep increasing the allocated size
char *input = calloc(1, 1); // space for '\0'
size_t len = 0;
for (;;) {
int ch = getchar();
if (ch != '\n') {
input[len] = ch; // replace '\0' with ch
len++;
char *tmp = realloc(input, len + 1);
if (tmp == NULL) exit(EXIT_FAILURE);
input = tmp;
input[len] = 0; // add '\0'
} else {
break;
}
}
// use input and len
free(input);
Compiles without warnings or errors, just the following code crashes when I try to either read from or write to the matrix constValues.
It needs to be passed to another function to be read from also; the function createOutputLine.
How can I point to the data held correctly so it can be modified and read from? Thanks.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <stdbool.h>
void createOutputFile(FILE*, int, char**);
char createOutputLine(int, int, char*, char**);
int main(int argc, char **argv) {
int removeComments = 0;
FILE *file;
if (argc > 1 && strcmp(argv[1], "-i") == 0) {
if (argc > 2) {
if (!(file = fopen(argv[2], "r"))) {
printf("Error: file not found");
return -1;
}
}
else {
printf("Error: no file specified");
return -1;
}
}
else {
printf("Error: command requires -i");
return -2;
}
createOutputFile(file, argc, argv);
fclose(file);
}
void createOutputFile(FILE *file, int argc, char **argv) {
fseek(file, 0, SEEK_SET);
char *data = (char*)malloc(2000);
FILE *header;
char name[20];
char *token = strtok(argv[2], ".");
strcpy(name, strcat(token, ".o"));
FILE *output = fopen(name, "w");
char constNames[10][15];
char **constValues[10][10];
int constsStored = 0;
while (fgets(data, 2000, file) != NULL) {
for (int i = 0; i < strlen(data); i++) {
int c = i;
bool linePrinted = false;
if (data[i] == '#' && data[i + 1] == 'd') {
for (c = i; c <= i + 7; c++) {
data[c] = '\0';
} int ch = 0;
while (data[c] != ' ') {
constNames[constsStored][ch] = data[c];
data[c] = '\0';
ch++;
c++;
} ch = 0;
while (data[c] != '\n') {
**constValues[constsStored][ch] = data[c]; //this line crashes
data[c] = '\0';
ch++;
c++;
}
if (data[c] == '\n') data[c] = '\0';
constsStored++;
}
for (int ch = 0; ch <= constsStored; ch++) {
if (data[i] == constNames[ch][0]) {
int ch2 = i + 1;
int ch3 = 1;
bool isConst = false;
while (data[ch2] != ' ') {
if (data[ch2] == constNames[ch][ch3] && isConst == false) isConst = true;
ch2++;
ch3++;
}
if (isConst || data[i + 1] == ' ') {
char line[200];
line[200] = createOutputLine(i, ch, data, **constValues);
fprintf(output, "%c", line[200]);
linePrinted = true;
}
}
}
if (!linePrinted)
fprintf(output, "%c", data[i]);
}
}
fclose(output);
free(data);
}
char createOutputLine(int i, int constElem, char *data, char **constValues) {
int ch = i;
int ch2 = 0;
char temp[200];
while (data[ch] != '\n' && data[ch] != ' ' && data[ch] != ';') {
temp[ch2] = data[ch];
printf("%c", data[ch]);
ch++;
ch2++;
}
char line[200];
ch2 = 0;
for (ch = i; ch <= sizeof(data); ch++) {
line[ch2] = data[ch];
ch2++;
}
for (ch = 0; ch <= 10; ch++) {
line[ch2] = constValues[constElem][ch];
ch2++;
}
for (ch = 0; ch <= sizeof(temp); ch++) {
line[ch2] = temp[ch];
ch2++;
}
line[ch2 + 1] = '\n';
return line[200];
}
A pointer shall point to an object before it can be derefenced. Full stop.
char **constValues[10][10]; just declares an 2D array of pointers to pointers to characters. And as it is an automatic array (neither statically nor dynamically allocated), its pointers are just uninitialized.
When you late use **constValues[constsStored][ch] = data[c];, you try to dereference an uninitialized pointer which is explicitely Undefined Behaviour. You are lucky to get an immediate crash, because UB consequences can be apparently unrelated problems.
The normal way is to declare arrays of objects, and use the addresses of those objects for pointers.
That's not all: C arrays are not first class citizens. You cannot assign to array, nor return it from a function. So this is plain wrong:
char line[200];
line[200] = createOutputLine(i, ch, data, **constValues);
It just assigns the unique character returned by the function past the end of the array!
So is this:
char line[200];
...
return line[200];
It does not return an array (C does not allow it) but the value of the byte that happens to live past the array.
I am sorry, but there are too many errors for me to fix them is such a long program.
You may find C hard and ask for help. But build small code containing only what you want to work on. And only when those small pieces work correctly, try to assemble them in a larger program.
I have a program where my code uses a goto statement, and I want to get rid of it in a nice way, but I can't seem to find a solution. If goto is the best way, then please let me know. Here is a summary of the code:
//Counts how many times every word appears in a file
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NUMWORDS 1000
#define WORDLEN 50
typedef struct
{
char word[WORDLEN + 1];
int num;
} Appearance;
int main(int argc, char *argv[]) {
FILE *readfile;
Appearance *appearlist[NUMWORDS] = {NULL};
char word[WORDLEN + 1];
int i;
//Get a valid filename and open the file, store pointer into readfile
...
char c;
while (c != EOF) {
skip: //Annoying label
//Get a word from readfile, store into word
...
if (word[0] != '\0') {
for (i = 0; i < NUMWORDS && appearlist[i]; i++) {
if (strcmp(appearlist[i] -> word, word) == 0) {
appearlist[i] -> num++;
goto skip; //Annoying goto
}
}
appearlist[i] = (Appearance *) malloc(sizeof(Appearance));
appearlist[i] -> num = 1;
strcpy(appearlist[i] -> word, word);
}
}
//Display results, free memory
...
return 0;
}
The problem is, I want to skip code that is outside of the loop I want to skip from. I would like to not create another variable only designed for this. If you want the full code, click on "Show code snippet."
//Counts how many times every word appears in a file
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define NUMWORDS 1000
#define WORDLEN 50
#define FILENAMELEN 50
typedef struct
{
char word[WORDLEN + 1];
int num;
} Appearance;
int main(int argc, char *argv[])
{
char filename[FILENAMELEN];
FILE *readfile;
Appearance *appearlist[NUMWORDS] = {NULL};
char word[WORDLEN + 1];
size_t ln;
int i;
if (argc == 2)
strncpy(filename, argv[1], sizeof(filename));
else {
printf("Enter a filename to count appearances from, or just press enter to quit: ");
fgets(filename, FILENAMELEN, stdin);
ln = strlen(filename) - 1;
if (filename[ln] == '\n')
filename[ln] = '\0';
}
while((readfile = fopen(filename, "r")) == NULL) {
if (filename[0] == '\0')
return 0;
printf("Invalid file! Please enter another filename, or just press enter to quit: ");
fgets(filename, FILENAMELEN, stdin);
ln = strlen(filename) - 1;
if (filename[ln] == '\n') filename[ln] = '\0';
}
char c;
while (c != EOF) {
skip:
for (i = 0; (c = getc(readfile)) != EOF && (isalnum(c) || c == '\''); i++) {
if (i >= WORDLEN) {
word[i] = '\0';
printf("\nWarning: word too long (over %d characters), trimming to: %s\n", WORDLEN, word);
while ((c = getc(readfile)) != EOF && (isalnum(c) || c == '\'')) ;
} else {
word[i] = tolower(c);
}
}
word[i] = '\0';
if (word[0] != '\0') {
for (i = 0; i < NUMWORDS && appearlist[i]; i++) {
if (strcmp(appearlist[i] -> word, word) == 0) {
appearlist[i] -> num++;
goto skip;
}
}
appearlist[i] = (Appearance *) malloc(sizeof(Appearance));
appearlist[i] -> num = 1;
strcpy(appearlist[i] -> word, word);
}
}
for (i = 0; i < NUMWORDS && appearlist[i]; i++) {
printf("Word: %s, Appearances: %d\n", appearlist[i] -> word, appearlist[i] -> num);
free(appearlist[i]);
}
return 0;
}
Using goto in this case is often considered acceptable.
Alternatives would be to set a variable so that you can continue in the outer loop after breaking from the inner one, or turning the whole segment that you want to escape from into a separate function, and returning from it instead of using goto.
I'm ignoring any other issues there may be with the code that aren't relevant to the question!
Put everything beginning with the 'if' statement into a separate method (let's call it "process" and replace the goto with return. Then the while-loop becomes:
while (c != EOF) {
//Get a word from readfile, store into word
...
process(...);
}
Sometimes using goto is a hint that code should use a helper function
static bool findword(Appearance *appearlist, size_t size, const char *word) {
for (size_t i = 0; i < size && appearlist[i]; i++) {
if (strcmp(appearlist[i]->word, word) == 0) {
appearlist[i]->num++;
return true;
}
}
return false;
}
while (c != EOF) {
//Get a word from readfile, store into word
...
if (word[0] != '\0') {
if (findword(appearlist, NUMWORDS, word)) {
continue;
}
appearlist[i] = (Appearance *) malloc(sizeof(Appearance));
appearlist[i] -> num = 1;
strcpy(appearlist[i] -> word, word);
}
}
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <windows.h>
#include <conio.h>
int isnumber(char *temp) ;
void divide(char array[]);
void divide2(char array[]);
void append(char* s, char c);
int main()
{
char array[20];
scanf("%s",array);
divide2(array);
return 0;
}
int isnumber(char *temp) {
int i = 0;
int flag=0 ;
for (i=0;i<strlen(temp);i++) {
if (!isdigit(temp[i])){
flag = 1;
}
else if(temp[0]=='-' && isdigit(temp[i])){
flag=0;
}
}
return flag;
}
void divide2( char array[]){
char array1[20];
int j=0,i;
for(i=0 ; i<strlen(array1);i++)
{
array1[i]=NULL;
}
for(i=0;i<strlen(array);i++){
if(array[i]!='+'||array[i]!='-')
{
append(array1,array[i]);
j++;
}
else{
divide(array1);
for(i=0 ; i<strlen(array1);i++)
{
array1[i]='\0';
}
}
}
}
void divide(char array[]){
int co,pow,i;
char *token1;
char t[20];
char *t_3[2];
token1= strtok(array,"+");
strcpy(t,token1);
while(token1!=NULL){
t_3[0] = strtok(t,"x^");
t_3[1] = strtok(NULL,"x^");
if((t_3[0] == NULL)&&(t_3[1] == NULL)) {
co = 1;
pow = 1;
}
else if((token1[0]=='-')&& (token1[1]== 'x') && (t_3[1] != NULL)){
co=-1;
pow=atoi(t_3[1]);
}
else if ((token1[0]=='-') &&(t_3[0] != NULL)&&(t_3[1] != NULL)){
co=atoi(t_3[0]);
pow=atoi(t_3[1]);
}
else if((token1[0]=='-')&& (token1[1]== 'x') && (t_3[1] == NULL)){
co=-1;
pow=1;
}
else if(isnumber(token1)==0) {
co = atoi(t);
pow = 0;
}
else if ((t_3[0] != NULL)&&(t_3[1] == NULL) && (token1[0]=='x')){
pow = atoi(t_3[0]);
co= 1;
}
else if ((t_3[0] != NULL)&&(t_3[1] == NULL)) {
co = atoi(t_3[0]);
pow = 1;
}
else {
co = atoi(t_3[0]);
pow = atoi(t_3[1]);
}
printf("coefficient is : %d power is :%d\n",co,pow);
co=0;
pow=0;
t_3[0]='\0';
t_3[1]='\0';
for(i=0 ; i<sizeof(t);i++){
t[i]='\0';
}
token1 = strtok(NULL,"+");
if(token1==NULL){
printf("...............");
printf("\n");
}
else{
strcat(t,token1);
}
}
}
void append(char* s, char c)
{
int len = strlen(s);
s[len] = c;
s[len+1] = '\0';
}
This code is supposed to split polynomials and print their power and coefficient but I keep getting the error undefined reference to append. Can any one tell me why? I have tried searching for this error but did not find a solution .
i fixed the problem .. but the function itself won't work
if(array[i]!='+'||array[i]!='-')
is always true. You mean (I think)
if(array[i]!='+'&& array[i]!='-')