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!
Related
I am trying to make a program that would take a sentence from the user and reverse the order of the words while keeping the special characters ['.','?','!'] at the end.
the problem I'm getting is that I get weird symbols after the last word and the special character.
I am programming using C.
I think it's because the last element printed is not a '\0'.
but I don't know how to fix that.
My code:
#include <ctype.h>
#define N 200
int main()
{
char arr[N] = { 0 };
char* p, * q, mark = 0;
int c;
p = arr;
printf("Enter a sentence: ");
while ((c = getchar()) != '\n' && p < arr + N)
{
if (c == '?' || c == '.' || c == '!')
{
mark = c;
break;
}
else
*p++ = c;
}
*p = '\0';
printf("Reversal of sentence: ");
while (p >= arr)
{
while (*--p != ' ' && p != arr);
if (p == arr) {q = arr;}
else {q = p + 1;}
while (*q != '\0' && *q != ' ')
{
printf("%c", *q++);
}
if (p >= arr)
{
printf(" ");
}
}
printf("%c", mark);
printf("\n");
return 0;
}
I've fixed the overflow error when reading the sentence by removing the \0 termination. The input string is never used by anything that cares. I've also added a check for End-Of-File.
Next I changed the reversal loop to not underflow and fixed outputing an extra ' ' before the mark.
Last the printf calls can use putchar instead.
#include <ctype.h>
#include <stdio.h>
#define N 200
int main()
{
char arr[N] = { 0 }; // initialization optional, nothing cares
char* p, * q, mark = 0;
int c;
p = arr;
printf("Enter a sentence: ");
while ((c = getchar()) != '\n' && c != EOF && p < arr + N)
{
if (c == '?' || c == '.' || c == '!')
{
mark = c;
break;
}
else
*p++ = c;
}
printf("Reversal of sentence: ");
while (p > arr)
{
while (*--p != ' ' && p != arr);
if (p == arr) {q = arr;}
else {q = p + 1;}
while (*q != '\0' && *q != ' ')
{
putchar(*q++);
}
if (p > arr)
{
putchar(' ');
}
}
putchar(mark);
putchar('\n');
return 0;
}
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.
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 am trying to count the number of loops and emptylines in a string entered by a user. So here is the way I did it:
#include <stdio.h>
#include<stdlib.h>
#include <string.h>
int main(void) {
int i, lines, loopF = 0, loopW = 0, loopDW = 0, empty = 0;
char *p, str[200];
const char test[10] = "while";
char *f;
printf("Enter a string. Ctrl+Z for exit.\n");
while (fgets(str, 200, stdin) != NULL) {
if (f = strstr(str, test)) { //first way
loopW++;
}
for (i = 0; i < strlen(str); i++) {
// count loops
if (str[i] == 'f' && str[i + 1] == 'o' && str[i + 2] == 'r') {
loopF++;
}
if (str[i] == 'w' && str[i + 1] == 'h' && str[i + 2] == 'i'
&& str[i + 3] == 'l' && str[i + 4] == 'e') { // second way
loopW++;
}
if (str[i] == 'd' && str[i + 1] == 'o') {
loopDW++;
if (loopDW >= 1)
loopW--;
}
}
// count empty lines
p = str;
lines = 0;
while (*p != '\n') {
if (*p != ' ') {
lines = 1;
}
p++;
}
if (!lines) {
empty++;
lines = 0;
}
}
printf("---------------------\n");
printf(" Empty lines: %d \n\n", empty);
printf(" Number of loops:\n");
printf(" For: %d \n", loopF);
printf(" While: %d \n", loopW);
printf(" Do/While: %d \n", loopDW);
printf("---------------------\n");
return 0;
}
I did it for 2 ways only for "while" to test but when a user types "whilethis" or "thiswhile" it counts it(which is not what I want). I want when there is only a while(a loop) to be counted and not with other symbols but i have no idea how to do it. Same is for do/while and for loops. Any help here? :)
The proper solution also needs to handle strings and comments
print("I have no for() loops")
/* commented out for() loop */
char* c = "for()\"loop\\";
If you do not care about this, and really want to use plain C, I would recommend "strtok" function which splits string into the words using delimiters (which would be basically all non-alphanumeric symbols in your case -- space, brackets, comma, etc...). Then once you have words, you can just strcmp() them with "do", "while" or "for"
Unnecessarily complete source code:
#include <stdio.h>
main()
{
int c; //char read from stdin. Type is int to accomodate EOF
int x; //generic counter
int nl_counter = 1; //new line counter
int parens, brackets, braces, dubQuotes, singQuotes, comments; //stores number of unmatched pair occurences
int parenLines[99], bracketLines[99], braceLines[99], dubQuoteLines[99], singQuoteLines[99], commentLines[99]; //stores lines of unmatched pair occurences
int inParen, inBracket, inBrace, inDubQuote, inSingQuote, inComment; //checks whether reading inbetween a potentially matching pair
comments = parens = brackets = braces = dubQuotes = singQuotes = inComment = inParen = inBracket = inBrace = inDubQuote = inSingQuote = 0; //initializes whether in matching pairs to zero
for(x = 0; x < 99; x++) //initialize line occurences with zero
parenLines[x] = bracketLines[x] = braceLines[x] = dubQuoteLines[x] = singQuoteLines[x] = commentLines[x] = 0; //
//Read from stdin
while((c = getc(stdin)) != EOF)
{
if(c == '\n')
nl_counter++;
if(c == '/' && inComment == 0) //opens comment
{
c = getc(stdin);
if(c == '*')
{
inComment = 1;
commentLines[comments] = nl_counter;
comments++;
}
else if(c == '\n')
nl_counter++;
}
if(inComment == 1) //checks for close comment
{
if(c == '*')
{
c = getc(stdin);
if(c == '/')
{
inComment = 0;
comments--;
}
else if(c == '\n')
nl_counter++;
}
}
if(c == '(' && inComment == 0) //opens parenthesis
{
inParen = 1;
parenLines[parens] = nl_counter;
parens++;
}
if(inParen == 1 && inComment == 0) //checks for close parenthesis
{
if(c == ')')
{
inParen = 0;
parens--;
}
}
if(c == '[' && inComment == 0) //opens bracket
{
inBracket = 1;
bracketLines[brackets] = nl_counter;
brackets++;
}
if(inBracket == 1 && inComment == 0) //checks for close bracket
{
if(c == ']')
{
inBracket = 0;
brackets--;
}
}
if(c == '{' && inComment == 0) //opens brace
{
inBrace = 1;
braceLines[braces] = nl_counter;
braces++;
}
if(inBrace == 1 && inComment == 0) //checks for close brace
{
if(c == '}')
{
inBrace = 0;
braces--;
}
}
if(c == '\"' && inComment == 0 && inDubQuote == 0) //opens dubQuote
{
inDubQuote = 1;
dubQuoteLines[dubQuotes] = nl_counter;
dubQuotes++;
}
else if(inDubQuote == 1 && inComment == 0) //checks for close dubQuote
{
if(c == '\"')
{
inDubQuote = 0;
dubQuotes--;
}
}
if(c == '\'' && inComment == 0 && inSingQuote == 0) //opens single quote
{
inSingQuote = 1;
singQuoteLines[singQuotes] = nl_counter;
singQuotes++;
}
else if(inSingQuote == 1 && inComment == 0) //checks for close single quote
{
if(c == '\'')
{
inSingQuote = 0;
singQuotes--;
}
}
}
//display collected data
if(parens > 0)
{
for(x = 0; x < parens; x++)
printf("unmatched parenthesis on line %d\n", parenLines[x]);
printf("\n");
}
if(brackets > 0)
{
for(x = 0; x < brackets; x++)
printf("unmatched bracket on line %d\n", bracketLines[x]);
printf("\n");
}
if(braces > 0)
{
for(x = 0; x < braces; x++)
printf("unmatched brace on line %d\n", braceLines[x]);
printf("\n");
}
if(dubQuotes > 0)
{
for(x = 0; x < dubQuotes; x++)
printf("unmatched double quote on line %d\n", dubQuoteLines[x]);
printf("\n");
}
if(singQuotes > 0)
{
for(x = 0; x < singQuotes; x++)
printf("unmatched single quote on line %d\n", singQuoteLines[x]);
printf("\n");
}
if(comments > 0)
{
for(x = 0; x < comments; x++)
printf("unmatched comment on line %d\n", commentLines[x]);
printf("\n");
}
getc(stdin); //wait for input before exit
getc(stdin); //
}
Less unnecessarily complete source code (to the point):
#include <stdio.h>
main()
{
int c; //char read from stdin. Type is int to accomodate EOF
int x; //generic counter
int nl_counter = 1; //new line counter
int dubQuotes, singQuotes; //stores number of unmatched pair occurences
int dubQuoteLines[99], singQuoteLines[99]; //stores lines of unmatched pair occurences
int inDubQuote, inSingQuote; //checks whether reading inbetween a potentially matching pair
dubQuotes = singQuotes = inDubQuote = inSingQuote = 0; //initializes whether in matching pairs to zero
for(x = 0; x > 99; x++) //initialize line occurences with zero
dubQuoteLines[x] = singQuoteLines[x] = 0; //
//Read from stdin
while((c = getc(stdin)) != EOF)
{
if(c == '\n')
nl_counter++;
if(c == '\"' && inDubQuote == 0) //opens dubQuote
{
inDubQuote = 1;
dubQuoteLines[dubQuotes] = nl_counter;
dubQuotes++;
}
else if(inDubQuote == 1) //checks for close dubQuote
{
if(c == '\"')
{
inDubQuote = 0;
dubQuotes--;
}
}
if(c == '\'' && inSingQuote == 0) //opens single quote
{
inSingQuote = 1;
singQuoteLines[singQuotes] = nl_counter;
singQuotes++;
}
else if(inSingQuote == 1) //checks for close single quote
{
if(c == '\'')
{
inSingQuote = 0;
singQuotes--;
}
}
}
//display collected data
if(dubQuotes > 0)
{
for(x = 0; x < dubQuotes; x++)
printf("unmatched double quote on line %d\n", dubQuoteLines[x]);
printf("\n");
}
if(singQuotes > 0)
{
for(x = 0; x < singQuotes; x++)
printf("unmatched single quote on line %d\n", singQuoteLines[x]);
printf("\n");
}
getc(stdin); //wait for input before exit
getc(stdin); //
}
I haven't gotten to writing for escape sequences just yet, but still, I don't see why all the brackets and braces work, but if I put a " and then after pressing enter and ^z(EOF), it doesn't display my "unmatched double quote on line 1" message. I compensated for the fact that theyre the same character with an if-else, and the additional && inSingQuote == 0 / && inDubQuote == 0 in the initial checking for an opening quote. I just don't see any holes in the logic..
You forget to reset the flag inDubQuote to 0 when a newline is encountered. Therefore, when there is an error, the flag carries over to the next line, and in that the first double quote resets it and the next (a correctly closing one) will add an error flag for that line instead.
With simple, line by line debugging printfs added (and a proposed simpler structure for the if), it looks like that addition solves it:
printf ("(%d)", nl_counter);
//Read from stdin
while((c = getc(stdin)) != EOF)
{
if(c == '\n')
{
inDubQuote = 0;
nl_counter++;
printf ("(%d)", nl_counter);
}
if(c == '\"')
{
if (inDubQuote == 0) //opens dubQuote
{
inDubQuote = 1;
dubQuoteLines[dubQuotes] = nl_counter;
printf ("I just set #%d to %d!\n", dubQuotes, nl_counter);
dubQuotes++;
}
else //checks for close dubQuote
{
inDubQuote = 0;
dubQuotes--;
printf ("I just reset counter to #%d!\n", dubQuotes);
}
}
}
With some random input, it behaves as expected:
~/Documents $ ./a.out
(1)a"bc"d
i just set #0 to 1!
i just reset counter to #0!
(2)e"f"g"h
i just set #0 to 2!
i just reset counter to #0!
i just set #0 to 2!
(3)i"j"k"l"m
i just set #1 to 3!
i just reset counter to #1!
i just set #1 to 3!
i just reset counter to #1!
(4)n"o"p"q
i just set #1 to 4!
i just reset counter to #1!
i just set #1 to 4!
(5)r"s"t"u"v
i just set #2 to 5!
i just reset counter to #2!
i just set #2 to 5!
i just reset counter to #2!
(6)^D
unmatched double quote on line 2
unmatched double quote on line 4
You can do the same for single quotes but do note that it will not flag errors correctly with nested levels of single and double quotes (and your plethora of other Begin/End markers). If you want to do that, you need a smallish stack of characters on which you 'push' and 'pop' all of the various characters; then you'd flag an error when you 'pop' one for a pair where you did not yet 'push' it – and at the end of a line, this stack ought to be empty.