I'm kinda new to C programming and decided that making a brainfuck interpreter in C would be a good way to learn the language. I could write and tested with these bf codes:
this should print a hello world
++++++++[>++++[>++>+++>+++>+<<<<-]>+>+>->>+[<]<-]>>.>---.+++++++..+++.>>.<-.<.+++.------.--------.>>+.>++.
this works as expected, so i thought my interpreter worked fine, but when I tested with a few variants of the hello world code, strange things happened.
this bf code should also print a hello world, but instead it prints out ²♣■■ÖFu ÖÖ■♦u
--<-<<+[+[<+>--->->->-<<<]>]<<--.<++++++.<<-..<<.<+.>>.>>.<<<.+++.>>.>>-.<<<+.
this bf code should also print a hello world, but instead the program gets stuck
+[-->-[>>+>-----<<]<--<---]>-.>>>+.>>..+++[.>]<<<<.+++.------.<<-.>>>>+.
this is the code I wrote to interprete brainfuck:
#include <stdio.h>
int main(int argc, char const *argv[])
{
if (argc == 1)
{
printf("You must specify a file path\n");
return -1;
}
//amount of memory locations available
int mem = 30000;
//creating an integer array with mem positions
char arr[mem];
//current memory position
int index = 0;
//setting everything to 0
for (int i = 0; i < mem; i++)
{
arr[i] = 0;
}
FILE *file = fopen(argv[1], "r");
if (file == NULL)
{
printf("ERROR, file couldn't be read\n");
return -1;
}
//reading util the END OF THE FILE
char c;
while ((c = fgetc(file)) != EOF)
{
if (c == '+')
{
arr[index]++;
}
else if (c == '-')
{
arr[index]--;
}
else if (c == '>')
{
index++;
index %= mem;
}
else if (c == '<')
{
index--;
index %= mem;
}
else if (c == '.')
{
printf("%c", arr[index]);
}
else if (c == ',')
{
scanf("%c", &arr[index]);
}
else if (c == '[')
{
char temp = fgetc(file);
int skip = 0;
while (temp != ']' || skip != 0)
{
if (temp == '[')
skip++;
if (temp == ']' && skip > 0)
skip--;
temp = fgetc(file);
}
fseek(file, -1, SEEK_CUR);
}
else if (c == ']')
{
if (arr[index] != 0)
{
fseek(file, -2, SEEK_CUR);
char temp = fgetc(file);
int skip = 0;
while (temp != '[' || skip != 0)
{
if (temp == ']')
skip++;
if (temp == '[' && skip > 0)
skip--;
fseek(file, -2, SEEK_CUR);
temp = fgetc(file);
}
}
else
{
continue;
}
}
}
fclose(file);
return 0;
}
Thanks a lot if you can help me out on this one.
There's could be a problem with this piece of code, when index become negative.
index--;
index %= mem;
% operator retains the sign of the left argument, so -1 % mem is –1, not mem–1 you may expect.
Related
I have been trying to create a search function based exclusively on arrays rather than strings. The problem that I currently seem to be finding is that the code is tagging locations, without actually finding the correct letters. The end goal is for the code to find the full word and state how many characters it is into the line. Any help would be greatly appreciated.
int main()
{
int read = 1, i = 0, z = 0, q, o = 0, b;
char a[15];
char letters [] = "HELLOMYNAMEISELDERPRICEANDIHAVECOMETOSHAREWITHYOUTHISMOSTAMAZINGBOOK";
printf("HELLOMYNAMEISELDERPRICEANDIHAVECOMETOSHAREWITHYOUTHISMOSTAMAZINGBOOK\n");
printf("Please type in a word to search for in upper case:\n");
scanf(" %c", &a[1]);
scanf("%c", &a[2]);
if (a[2] != '\n') {scanf("%c", &a[3]); q=2;}
if (read == 1) {if (a[3] != '\n') {scanf("%c", &a[4]); q=3;} else read = 0;}
if (read == 1) {if (a[4] != '\n') {scanf("%c", &a[5]); q=4;} else read = 0;}
if (read == 1) {if (a[5] != '\n') {scanf("%c", &a[6]); q=5;} else read = 0;}
if (read == 1) {if (a[6] != '\n') {scanf("%c", &a[7]); q=6;} else read = 0;}
if (read == 1) {if (a[7] != '\n') {scanf("%c", &a[8]); q=7;} else read = 0;}
if (read == 1) {if (a[8] != '\n') {scanf("%c", &a[9]); q=8;} else read = 0;}
if (read == 1) {if (a[9] != '\n') {scanf("%c", &a[10]); q=9;} else read = 0;}
if (read == 1) {if (a[10] != '\n') {scanf("%c", &a[11]); q=10;} else read = 0;}
if (read == 1) {if (a[11] != '\n') {scanf("%c", &a[12]); q=11;} else read = 0;}
if (read == 1) {if (a[12] != '\n') {scanf("%c", &a[13]); q=12;} else read = 0;}
if (read == 1) {if (a[13] != '\n') {scanf("%c", &a[14]); q=13;} else read = 0;}
if (read == 1) {if (a[14] != '\n') {scanf("%c", &a[15]); q=14;} else read = 0;}
while (i != 1){
printf("line read\n");
if (a[1] == letters[z]){
printf("Found");
for (int p=0; p < q; p++){
o = z+p;
printf("checking for word\n");
if (a[p] == letters[o]){
printf("That bitch");}
else {break;}
}}
z++;
if (letters[z]=='\n'){i = 1;}
}
printf("%c", letters[z]);
printf("hmmm");
}
This redefined code should work for you:
#include <stdio.h>
#include <string.h>
int main()
{
char str[] = "HELLOMYNAMEISELDERPRICEANDIHAVECOMETOSHAREWITHYOUTHISMOSTAMAZINGBOOK";
char letter[100];
int i, j, k, counter;
i = j = k = counter = 0;
printf("%s\n", str);
printf("Enter a substring to find: ");
scanf("%s", letter);
for (i = 0; str[i]; i++) { // str[i] != '\0'
if (str[i] == letter[j]) {
for (k = i, j = 0; str[k] && letter[j]; j++, k++)
if (str[k] != letter[j])
break;
if (!letter[j]) { // when letter[j] meets false and substring found
printf("\nFound at %d!\n", counter);
return 0;
}
} else {
printf("."); // for decoration
counter++;
}
}
printf(" No matches!\n");
return 0;
}
Sample Output
HELLOMYNAMEISELDERPRICEANDIHAVECOMETOSHAREWITHYOUTHISMOSTAMAZINGBOOK
Enter a substring to find: BOOK
................................................................
Found at 64!
I am working on a question which requires me to print a string given a field-number at that position. The strings should be read from a file.
file.txt
C is a language.
lex lexical analyser
(blank line)
gcc is good
If the field-number is 2 (i.e the second word in the sentence). The program should output
is
lexical
(NULL)
is
I wrote a function but don't think its the correct way and that it would work for all cases. It should handle extra blanks or newlines.
while (fgets(buffer, MAX, file) != NULL) {
for (int i = 1; i < strlen(buffer); i++) {
if (count == field_number - 1) {
int j = i;
while (j < strlen(buffer) && buffer[j] != ' ') {
printf("%c", buffer[j++]);
}
printf("\n");
count = 0;
break;
}
if (buffer[i] == ' ' && buffer[i - 1] != ' ') {
count++;
}
}
}
I am a beginner. This code should be easy to understand.
This should work for all the cases,
int main() {
//FILE* file = fopen(__FILE__, "r");
//int field_number = 2;
int new_line = 0; // var to keep track of new line came or not
int word = 0;
int count = 0;
char c, prev_c;
while ((c = fgetc(file)) != EOF) {
// printf("[%c]", c);
// if a new line char comes it means you entered a new line
if(c == '\n') {
// you have to print the new line here on the output to handle
// empty line cases
printf("\n");
new_line = 1; // when line changes
word = 0; // no word has come in this new line so far
count = 0; // count becomes 0
} else if( c == ' ' && prev_c != ' ') {
if(word)
count++;
if(count == field_number) // if count exceeds field_number
new_line = 0; // wait till next line comes
} else if (new_line && count == field_number - 1) {
printf("%c", c);
} else {
word = 1; // fi a not new line or non space char comes, a word has come
}
prev_c = c;
}
return 0;
}
I am reading in a string character by character then for each word found(separated by space) counting the length of each word, and finally printing all that information to the screen.
Sample run: trickier to master
n=8, s=[trickier]
n=2, s=[to]
n=6, s=[master]
n=0, s=[]
n=-1, s=[]
This is correct what I get is this:
n=0, s=[]
n=0, s=[]
n=8, s=[trickier]
n=2, s=[to]
n=0, s=[]
n=6, s=[master]
n=0, s=[]
n=-1, s=[]
The problem is the leading spaces in the string I have looked at a lot of examples of how to trim the leading spaces, but I couldn't get anything to work with my current source code.
Code:
#include "getword.h"
int getword(char *w) {
int iochar;
int index = 0;
int numberofchars = 0;
if (numberofchars == 0 && iochar == '\n') {
w[index] = '\0';
iochar = EOF;
return 0;
}
if (iochar == EOF && numberofchars == 0) {
w[index] = '\0';
return -1;
}
while ((iochar = getchar()) != EOF) {
if (iochar != ' ' && iochar != '\n') {
w[index] = iochar;
index++;
numberofchars++;
} else {
w[index] = '\0';
if (strcmp(w, "done") == 0) {
return -1;
} else {
return numberofchars;
}
}
} //after while loop
} // end of function
int main() {
int c;
char s[STORAGE];
for (;;) {
(void)printf("n=%d, s=[%s]\n", c = getword(s), s);
if (c == -1)
break;
}
}
The code is way too complicated, with some useless and bogus tests producing undefined behavior:
testing iochar in getword() before you even read it with getchar() makes no sense.
combining reading, testing and writing the words in a single printf() call is bogus too: you should instead read, then test, then output if not done.
Here is a simplified version:
#include <stdio.h>
#include <string.h>
#define STORAGE 50
// read a word into an array of size `size`.
// return the number of characters read.
int getword(char *w, size_t size) {
int c;
size_t i = 0;
while (i + 1 < size && (c = getchar()) != EOF) {
if (c == ' ' || c == '\t' || c == '\n') {
if (i == 0)
continue; // ignore leading spaces
else
break; // stop on white space following the word.
}
w[i++] = c;
}
w[i] = '\0';
return i;
}
int main() {
char s[STORAGE];
int len;
while ((len = getword(s, sizeof s)) != 0) {
if (!strcmp(s, "done"))
break;
printf("n=%d, s=[%s]\n", len, s);
}
return 0;
}
I tried to make the code produce desired output, but this is all I could do. There were some bugs which I thought and so I fixed them. See the comments in the code for more details. Hope that solves the problem.
int getword(char * w) {
int iochar = 0;
int index = 0;
int numberofchars = 0;
// I really don't know why those if conditions were required
// Thought they were useless so removed them
while ((iochar = getchar()) != EOF) {
if (iochar != ' ' && iochar != '\n') {
w[index++] = iochar; // slight change here
numberofchars++;
} else {
w[index] = '\0';
// I don't know what this condition is supposed to mean
// so I ignored it
if (strcmp(w, "done") == 0) {
return -1;
} else {
return numberofchars;
}
}
} //after while loop
// Since EOF is encountered, no more characters to read
// So terminate the string with '\0'
w[index] = '\0';
// Here after the loop you should check if some characters were read, but not
// handled. If there are any, return them because that's what you last read
// before EOF was encountered
return (numberofchars > 0 ? numberofchars : -1);
} // end of function
int main()
{
int c;
char s[STORAGE];
for (;;) {
// Put the if condition before printing because if -1 is returned
// it doesn't make sense to print the string at all
c = getword(s);
if (c == -1) break;
printf("n=%d, s=[%s]\n", c, s);
}
}
Here's where I tested this: http://ideone.com/bmfaA3
I am writing a program to count words as practice but I am running into a problem where it is incorrectly counting no matter which option I choose.
#include <stdio.h>
#include <stdbool.h>
#include <string.h>
int main(int argc, char **argv){
int totalcount = 0; //hold overall count
for(int i = 2; i < argc; i++){
int count = 0; //hold count for each file
int c; //temporarily hold char from file
FILE *file = fopen(argv[i], "r");
if (strcmp("-c",argv[1])){
while((c = fgetc(file)) != EOF){
count++;
}
}
else if(strcmp("-w",argv[1])){
bool toggle = false; //keeps track whether the next space or line indicates a word
while((c = fgetc(file)) != EOF){
if(!toggle && ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))){
toggle = true;
}
if(toggle && ((c == '\n') || (c == ' '))){
count++;
toggle = false;
}
}
}
else{
while((c = fgetc(file)) != EOF){
if(c == '\n'){
count++;
}
}
}
printf("%d %s", count, argv[i]);
fclose(file);
totalcount += count;
}
if (argc > 3){
printf("%d total", totalcount);
}
return 0;
}
I don't know why my logic for char count doesn't work. I have ran through my logic when writing each section and it doesnt make sense to me why it would not me working. Any help would be greatly appreciated.
strcmp returns 0 when the strings equal, so never enter into the if/else statement
if (strcmp("-c",argv[1]) == 0){ //return value is 0
while((c = fgetc(file)) != EOF){
count++;
}
}
else if(strcmp("-w",argv[1]) == 0){ //return value is 0
bool toggle = false; //keeps track whether the next space or line indicates a word
while((c = fgetc(file)) != EOF){
if(!toggle && ((c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z'))){
toggle = true;
}
if(toggle && ((c == '\n') || (c == ' '))){
count++;
toggle = false;
}
}
}
Hope it works for you
You can read file line by line, it may simplify the task
int get_lines_chars(const char *path)
{
/* Open templorary file */
FILE *fp = fopen(path, "r");
if (fp != NULL)
{
ssize_t read;
size_t len = 0;
char *line = NULL;
unsigned int line_no, char_no;
line_no = char_no = 0;
/* Read line-by-line */
while ((read = getline(&line, &len, fp)) != -1)
{
int curr_line = 0;
while (*line)
{
curr_line++;
char_no++;
line++;
}
line -= curr_line;
line_no++;
}
/* Cleanup */
fclose(fp);
if(line) free(line);
printf("File has %d lines and %d chars\n", line_no, char_no);
return 1;
}
return 0;
}
I want to print a bunch of words with their definitions in this format (word:defn) from a text file. However, I experience a segmentation error when running the program using gcc on a server. The weird thing is that when I compile the C program on a local desktop the program works perfectly.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int read_dict() {
FILE *fp;
int c;
char word[50];
char defn[500];
int sep = 0;
int doublenew = 0;
int i = 0;
fp = fopen("textfile.txt", "r");
if (fp == NULL) {
perror("Error in opening file");
return (-1);
}
while ((c = fgetc(fp)) != EOF) {
if (feof(fp)) {
break;
}
if (c == '.' && sep == 0) {
sep = 1;
word[i] = '\0';
//c = fgetc(fp);
i = 0;
} else
if (doublenew == 1 && c == '\n' && sep == 1) {
defn[i] = c;
i++;
defn[i] = '\0';
printf("%s %s", word, defn);
i = 0;
sep = 0;
doublenew = 0;
} else
if (c == '\n' && sep == 1) {
defn[i] = c;
doublenew = 1;
i++;
} else
if (sep == 0) {
word[i] = c;
i++;
} else
if (sep == 1) {
defn[i] = c;
i++;
doublenew = 0;
}
}
fclose(fp);
return 0;
}
text file:
COOKIE. is a small, flat, sweet, baked good, usually containing flour, eggs, sugar, and either butter, cooking oil or another oil or fat. It may include other ingredients such as raisins, oats, chocolate chips or nuts.
ICE CREAM. is a sweetened frozen food typically eaten as a snack or dessert.
The word length is limited to 49 characters and the definition to 499 characters, but you never check for overflow in your code. If, unlike your sample, the dictionary used on the server has longer words and/or definitions, your code invokes undefined behavior which can cause a segmentation fault.
Undefined behavior might also not cause any visible effect, as seems to be the case on your local machine. The code generated by the local compiler and that of the server may be different, due to a different version or different command line options.
Check for array boundaries to avoid this:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int read_dict() {
FILE *fp;
int c;
char word[50];
char defn[500];
int sep = 0;
int doublenew = 0;
size_t i = 0;
fp = fopen("textfile.txt", "r");
if (fp == NULL) {
perror("Error in opening file");
return (-1);
}
while ((c = fgetc(fp)) != EOF) {
if (feof(fp)) {
break;
}
if (c == '\r') {
/* ignore CR characters inserted by Windows before LF */
continue;
}
if (c == '.' && sep == 0) {
sep = 1;
word[i] = '\0';
//c = fgetc(fp);
i = 0;
} else
if (doublenew == 1 && c == '\n' && sep == 1) {
if (i < sizeof(defn) - 1) {
defn[i] = c;
i++;
}
defn[i] = '\0';
printf("%s %s", word, defn);
i = 0;
sep = 0;
doublenew = 0;
} else
if (c == '\n' && sep == 1) {
if (i < sizeof(defn) - 1) {
defn[i] = c;
i++;
}
doublenew = 1;
} else
if (sep == 0) {
if (i < sizeof(word) - 1) {
word[i] = c;
i++;
}
} else
if (sep == 1) {
if (i < sizeof(defn) - 1) {
defn[i] = c;
i++;
}
doublenew = 0;
}
}
fclose(fp);
return 0;
}
Note: if nothing gets printed on the server, it means the file does not have 2 consecutive newline characters '\n'. If you are using the same file on your system and on the server, and if you are using Windows on your system and Linux on your server, the behavior of your program will be different on the '\r' characters used by Windows for the end of line. You must ignore these characters explicitly as they are only implicitly ignored on Windows, not on Linux. I modified the code above to account for this.