Does space equal '\0' in C? How can I avoid confusing them? - c

I am writing a function that looks for the first 4 whole numbers separated by a comma in a string.
For example, if the string is:
123,4,9.5,av4,3,g1,1,6
the function will extract to a different array the numbers: 123,4,3,1
Everything works well until I try entering an input with a space in the middle, which is not supposed to be considered as a valid number, but then the loop stops once it bumps into the space. Is there a solution for that?
I'm not allowed to use any other library than stdio.h.
Here's my code:
int getParameters(int parameters[], int size) {
char input[100];
int indexInput = 0, indexParameters = 0;
int skip = 0, numberSeen = 0, negativeSeen = 0;
int i = 0;
scanf("%s", input);
for ( ; input[indexInput]!= '\0' && indexParameters < size; ++indexInput) {
if (input[indexInput] == ',' && skip == 1) {
parameters[indexParameters] = 0;
skip = 0;
negativeSeen = 0;
} else if (input[indexInput] == ',' && negativeSeen == 1 && numberSeen == 1) {
printf(ERROR);
return -1;
} else if (input[indexInput] == ','&& numberSeen == 1) {
numberSeen = 0;
indexParameters++;
} else if (input[indexInput] == ',') {
continue;
} else if (input[indexInput] == '-' && skip == 1) {
continue;
} else if (input[indexInput] == '-' && numberSeen == 0 && input[indexInput+1] != '-') {
negativeSeen = 1;
} else if (input[indexInput] <= '9' && input[indexInput] >= '0') {
parameters[indexParameters] *= 10;
parameters[indexParameters] += input[indexInput] - '0';
numberSeen = 1;
} else {
skip = 1;
}
}
if (skip == 1)
parameters[indexParameters] = 0;
while (i < 4) {
printf("%d,", parameters[i]);
++i;
}
return 0;
}

The name of the %s format specifier is a bit misleading, it matches a sequence of non-whitespace characters. As you can see it's meant to read a word, not the whole string.
Perhaps you want to read a whole line?

Related

Drawing Unicode box in C: the inner one of 2 nested for loop doesn't exit upon hitting the test condition

I'm trying to draw a box from Unicode chars and the problem is that the inner for loop doesn't seem to exit after hitting the condition of reaching 26 iterations, which leaves the output scrambled in one line and split in half.
I've tried replacing the initial values of loop counters with 2 (since it appears as if the first decision condition is skipped due to 0%2 == 0 producing an error, but to no avail.)
I've also tried replacing the spaces with 0 and add some printf tests, but it seems like the main issue is with my inability to decompose this program into modules and I have no idea how it can be performed, giving that the only basic action the function can do is print a character depending on the condition.
Should I try to generalize the edge cases and pass loop counters and the code of printable chars to a function, testing them on each iteration?
#include <stdio.h>
#include <wchar.h>
#include <locale.h>
wchar_t edgeLU = 0x250c;
wchar_t vert = 0x2502;
wchar_t leftMid = 0x251c;
wchar_t edgeLB = 0x2514;
wchar_t botMid = 0x2534;
wchar_t horiz = 0x2500;
wchar_t edgeRB = 0x2518;
wchar_t rightMid = 0x2524;
wchar_t edgeRU = 0x2510;
wchar_t upMid = 0x252c;
wchar_t cross = 0x253c;
int i, j;
int main() {
setlocale(LC_CTYPE, "");
for (i = 0; i < 27; i++) {
for (j = 0; j < 27; j++) {
if (i == 0) {
if (j == 0) {
wprintf(L"%lc", edgeLU);
}
else if (j%2 == 1) {
wprintf(L"%lc", horiz);
}
else if (j%2 == 0 && !(j == 0 || j == 26)) {
wprintf(L"%lc", upMid);
}
else {
wprintf(L"%lc", edgeRU);
}
}
else if (i%2 == 1) {
if (j%2 == 0) {
wprintf(L"%lc", vert);
}
else {
printf(" ");
}
}
else if (i%2 == 0 && !(i == 0 || i == 26)) {
if (j == 0) {
wprintf(L"%lc", leftMid);
}
else if (j%2 == 1) {
wprintf(L"%lc", horiz);
}
else if (j%2 == 0 && !(j == 0 || j == 26)) {
wprintf(L"%lc", cross);
}
else {
wprintf(L"%lc", rightMid);
}
}
else if (i == 26) {
if (j == 0) {
wprintf(L"%lc", edgeLB);
}
else if (j%2 == 1) {
wprintf(L"%lc", horiz);
}
else if (j%2 == 0 && !(j == 0 || j == 26)) {
wprintf(L"%lc", botMid);
}
else {
wprintf(L"%lc", edgeRB);
}
}
}
printf("\n");
}
return 0;
}
To avoid confusion, ┤ ┴ ├ ┬ are denoted as rightMid, botMid, leftMid and upMid respectively.
That is the output, the program first prints spaces from the (i%2 == 1) condition and newlines, following termination of the inner loop in some haphazard fashion.
In is undefined behaviour to mix wide and narrow character output to the same file. Replace printf calls with corresponding wprintf.

How to count matches?

Consedering 2 strings, I want to do a program in C that returns the number of possible matches between this 2 strings.
For example
$>./a.out "abc" "a*"
1
Because there is only 1 possible match : *="bc"
$>./a.out "abc" "a**"
3
Because there is only 3 possible matches : (*="bc", *="") ; (*="", *="bc") ; (*="b", *="c")
$>./a.out "ab cool ab cool ab" "ab*ab*"
2
Because there is 2 possible matches : (*=" cool ", *=" cool ab") ; (*=" cool ab cool ", *="")
I did a function "int match(char*, char*)" that returns true when there exists a match and false when there does not exist.
But i would like now to count the possible matches.
Any advices or suggestions?
int match(char* string, char* star) {
if (string[0] == '\0' && star[0] == '\0')
return 1;
else if (star[0] == '*')
return match(string, star+1);
else if (string[0] == '\0')
return 0;
else if (string[0] == star[0]){
if (star[-1] == '*') {
if (!match(string+1, star+1))
return match(string+1, star);
}
return match(string+1, star+1);
}
else if (string[0] != star[0] && star[-1] == '*')
return match(string+1, star);
else if (string[0] != star[0] && star[-1] != '*')
return 0;
}
int count_match(char* string, shar* star) {
int i;
for (i = 0; star[i] != '\0'; i += 1) {
if (star[i] != '*') {
if (star[i] != string[i])
return 0;
}
else {
int count = 0;
int j;
for (j = i; string[j] != '\0'; j += 1) {
count += count_match(string + j; star + i + 1);
count += count_match(string + j; star + i + 1);
return count;
}
}
return (string[i] == star[i]);
}

Count word in string

I'm trying to write a function to count occurrences of a particular word in a string. For example: Given string -
"Stop, time to go home. Todo fix me."
Letters "to" appeared three times (twice in different words); however, the word "to" appears only once. What should I do to count only word "to" (if will appear in string more times then count every single one). Any advice?
This is the code I was trying and playing around.
int word(char inputLine[]) {
int word = 0, i = 0, j = 0;
for (i = 0; inputLine[i] != '\0'; i++) {
if (inputLine[i] == 't' || inputLine[i] == 'o' || inputLine[i] != ' ') {
word++;
}
}
return word;
}
Try this:
int word(char inputLine[]) {
int word = 0, i = 0;
// stop before the last char
for (i = 0; inputLine[i] != '\0' && inputLine[i+1] != '\0'; i++) {
// is (T or t) and (O or o)
if ((inputLine[i] == 't' || inputLine[i] == 'T') && (inputLine[i+1] == 'o' || inputLine[i+1] == 'O')) {
// after the 'to' is not a letter
if ((inputLine[i+2] < 'a' || inputLine[i+2] > 'z') &&
(inputLine[i+2] < 'A' || inputLine[i+2] > 'Z')) {
// before is not a letter (or this is the start of the string)
if (i == 0 ||
((inputLine[i-1] < 'a' || inputLine[i-1] > 'z') &&
(inputLine[i-1] < 'A' || inputLine[i-1] > 'Z'))) {
word++;
}
}
}
}
return word;
}
The simplest way would be to use strtok. But, if you'd like to do it all by hand, the following will work. Although you only wanted the "to" this will work for any search string:
#include <stdio.h>
// word -- get number of string matches
int
word(char *input,char *str)
// input -- input buffer
// str -- string to search for within input
{
int chr;
int prev;
int off;
int stopflg;
int wordcnt;
off = -1;
stopflg = 0;
wordcnt = 0;
prev = 0;
for (chr = *input++; ! stopflg; prev = chr, chr = *input++) {
// we've hit the end of the buffer
stopflg = (chr == 0);
// convert whitespace characters to EOS [similar to what strtok might
// do]
switch (chr) {
case ' ':
case '\t':
case '\n':
case '\r':
chr = 0;
break;
}
++off;
// reset on mismatch
// NOTE: we _do_ compare EOS chars here
if (str[off] != chr) {
off = -1;
continue;
}
// we just matched
// if we're starting the word we must ensure we're not in the middle
// of one
if ((off == 0) && (prev != 0)) {
off = -1;
continue;
}
// at the end of a word -- got a match
if (chr == 0) {
++wordcnt;
off = -1;
continue;
}
}
return wordcnt;
}
void
tryout(int expcnt,char *buf)
{
int actcnt;
actcnt = word(buf,"to");
printf("%d/%d -- '%s'\n",expcnt,actcnt,buf);
}
// main -- main program
int
main(int argc,char **argv)
{
char *cp;
--argc;
++argv;
for (; argc > 0; --argc, ++argv) {
cp = *argv;
if (*cp != '-')
break;
switch (cp[1]) {
default:
break;
}
}
tryout(1,"to");
tryout(2,"to to");
tryout(1," to ");
tryout(1,"todo to");
tryout(2,"todo to to");
tryout(2,"doto to to");
tryout(1,"doto to doto");
tryout(0,"doto");
return 0;
}
If you must use only "basic" C functions the above solutions seems ok, but in the case you want to build a more scalable application (and you want to solve the problem in a smarter way) you can use a library that manipulate regular expressions. You can check this answer: Regular expressions in C: examples?
Regexes has the advantage that you can make the regex case unsensible (That is one of your issues).
I usually use pcre because it has the regex style of perl and java.
Here it is a very useful example that uses pcre: http://www.mitchr.me/SS/exampleCode/AUPG/pcre_example.c.html
Let's posit these rules:
"to" can be a word only when there is no char before and after it except the space char
If you accept those rules as valid and correct you need to check 4 conditions:
if (str[i]=='t'&& str[i+1]=='o'&& str[i-1]!='a-z'&& str[i+2]!='a-z'){
word++;
}
Two more conditions can be included to check for the upper case letters.
public class FindCountOfWordInString {
public static void main(String[] args) {
String str = "yhing ghingu jhhtring inghfg ajklingingd me";
String find = "ing";
int count = findCountOfWordInString(str, find);
System.out.println(count);
}
private static int findCountOfWordInString(String str, String find) {
String[] strArr = str.split(" ");
int count = 0, k = 0;
for (int i = 0; i < strArr.length; i++) {
if (strArr[i].contains(find)) {
String strCheck = strArr[i];
char[] findCharArr = find.toCharArray();
for (int j = 0; j < strCheck.length(); j++) {
if (strCheck.charAt(j) == findCharArr[k]) {
k++;
if (k == 3) {
count++;
k = 0;
}
} else {
k = 0;
}
}
}
}
return count;
}
}

K&R 1-24. Why isn't my program properly checking for matching single and double quotes?

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.

Checking two character arrays for equality C

I am trying to write a program that checks to see if a word inputed to a program matches one of the predefined keywords. Input is going to be coming from a text file and the text file will have a single word in it. So far the text file I have just has the word 'frog' which means the program should clearly print 'No Match Found' but it in fact prints 'Match Found' It prints prints 'Match Found' even when the word in the text file is a string of random letters. Here is my code, does anything stand out to you guys? Thanks
#define NUM 4
#define SIZE 12
int isAlpha(char);
//Returns 1 if it is an Alphabetical character, 0 if it is not
int isAlpha(char c) {
return (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z');
}
int main() {
char message[141];
int charCount = 0, c = 0, matchCheck = 0;
char keywords[NUM][SIZE] = {
"crackerjack",
"Hey",
"dog",
"feet"
};
//Removes non alphabetical characters
while((c = getchar()) != EOF && charCount <= 140) {
if(isAlpha(c)){
message[charCount] = c;
charCount++;
}
}
//checks if message matches keyword
for (int i = 0; i < NUM; i++) {
for (int j = 0; j < SIZE; j++) {
//Check if current two characters match
if (message[j] == keywords[i][j]) {
//Check if the two matched characters are the null terminator character
if (message[j] == '\0' && keywords[i][j] == '\0') {
matchCheck = 1;
break;
}
}
}
}
//prints "Match Found!" if there was a match
if (matchCheck == 1)
printf("Match Found!\n");
else
printf("No Match Found\n");
}
I havent programmed in C in a long time, and I dont have a C compiler with me right now. However, I think that there might be a problem with the logic. You need to check for every word individually. I would do somehting like the following for your last section ...
matchAnyWord = 0
for (int i = 0; i < NUM; i++) {
matchCheck = 1;
for (int j = 0; j < SIZE; j++) {
if (message[j] == '\0' && keywords[i][j] == '\0') break;
if (message[j] == '\0' && keywords[i][j] != '\0') { matchCheck = 0; break;}
if (message[j] != '\0' && keywords[i][j] == '\0') { matchCheck = 0; break;}
if (message[j] != keywords[i][j] ) { matchCheck = 0; break;}
}
if (matchCheck == 1) {matchAnyWord = 1; break;}
}
Note that here we check for the matching of individual words, and introduce a new variable matchAnyWord which is actually what you want. I might have errors in the syntax but I think the logic should be more-or-less there.
Cheers!
Also, not sure why the indentation isnt showing up correctly on my browser ...

Resources