I'm probably implementing this code in a terrible way, but i'm currently doing CS50 and trying to search my string for the char '. I searched for other chars such as text [i] == '!' however when doing text [i] == ''' it doesn't work correctly. Is it possible to make it work in this way?
Here's my terrible code if your interested... i'm trying to find the number of letters, words, and sentences.. it works other than the characters i can't define.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <ctype.h>
int main (void)
{
string text = get_string("Input text: "); //accept text input
int i;
int length = strlen(text);
int count = 0;
int count2 = 0;
int count3 = 0;
int excludeothers = (length - count);
for (i = 0; i < length; i++)
{
if(text[i] == ' ' || text [i] == '!' || text[i] == '?' || text[i] == '.' || text[i] == ',' || text[i] == '"' || text[i] == ':' || text[i] == ';' || text[i] == '-' || text[i] == ''') //check number of letters
{
count++;
}
}
for (i = 0; i <= length; i++)
{
if((text[i] == ' ' || text[i] == '\0') && (text[i-1] != ' ' || text[i-1] != '\0')) //check number of words
{
count2++;
}
}
for (i = 0; i < length; i++)
{
if((text[i] == '.' || text[i] == '?' || text [i] == '!') && (text[i+1] == ' ' || text[i+1] == '\0')) //check number of sentences
{
count3++;
}
}
printf("%i letters\n", excludeothers); //print letters
printf("%i words\n", count2); //print words
printf("%i sentences\n", count3); //print sentences
}
You need to escape it:
'\''
This means the single quote char. Same way you can have double quote in a string: "\""
Further reading: https://en.wikipedia.org/wiki/Escape_sequences_in_C
If you want to do it your way, then, yes, you need to escape that character. Take a look at GeeksForGeeks article about escaping characters in general. It will help you knowing which ones can be passed as normal characters and which ones will need a backslash in front of them.
However, if you are considering other options, take a look at strchr(). It is a builtin function that you can use. Using this will drastically improve and simplify your code. You can take a look at this question discussion for more information. And here is a reference for C documentation on this function.
Related
I'm doing a small project and I ran into a problem, when I want to correct a text that is a little big but not over the array size, I get this massage.
The problem is that I get it only after I input a large text (again not over the array size) and only if I want to exit the main, it print "Goodbye!" and corrupts the text.
Here is the code, I would love to get some help I'm really stuck
#include <stdio.h>
#include <string.h>
#define YES 1
#define NO 0
void main() {
char text[601], temp[601];
printf("*************** Welcome to the text cleaner ***************\n\n\n");
int stop = NO;
while (stop == NO) {
//gets text from user
printf("Please enter text:\n");
fgets(text, sizeof(text), stdin);
//wanted variables
int word = 0;
int car = 0;
int sen = 0;
int par = 0;
//value to check if current char is "
int paren = 0;
for (int i = 0; i < strlen(&text); i++) {
//checks for more than one space
if (text[i] == ' ') {
int x = i + 1;
if (text[x] == ' ') {
while (text[x] == ' ')
x++;
strcpy_s(&text[i + 1], strlen(&text), &text[x]);
}
}
//deletes spaces and adds space if needed before and after ,/.
if ((i > 0) && (text[i] == ' ') && (text[i + 1] == '.' || text[i + 1] == ',' || text[i - 1] == '\n' || text[i + 1] == '\n')) {
strcpy_s(&text[i], strlen(&text), &text[i + 1]);
}
if (text[i] == '.' || text[i] == ',')
if (text[i + 1] != ' ' && text[i + 1] != '.') {
strcpy_s(&temp, sizeof(temp), text);
text[i + 1] = '\0';
strncat_s(text, sizeof(text), " ", 1);
strncat_s(text, sizeof(text), &temp[i + 1], strlen(&temp[i + 1]));
}
//replace .. with . and row down
if (text[i] == '.')
if (text[i + 1] == '.') {
text[i + 1] = '\n';
}
//turns CAPITAL letter to lowercase, unless in ""
if (paren == 0) {
if (i > 1) {
if (text[i - 2] != '.') {
if (text[i] >= 'A' && text[i] <= 'Z')
text[i] = text[i] + 32;
}
}
}
//checks if letter should be CAPITAL, unless in ""
if (paren == 0) {
if (i == 0 || (i > 1) && (text[i - 2] == '.' || text[i - 1] == '\n')) {
if (text[i] >= 'a' && text[i] <= 'z')
text[i] = text[i] - 32;
}
}
//checks if enters to "" or exits
if (text[i] == '"') {
if (paren == 0)
paren++;
else
paren--;
}
// counts all parameters necesary
if (text[i] == ' ')
word++;
if (text[i] == '.')
sen++;
if (text[i] == '\n') {
par++;
word++;
}
}
//prints corrected text
car = strlen(text) - (par); //calculates like this to ignor all "\n" in array
printf("\nText after cleaning:\n------------------------------------------------------------------------------------------------\n%s", text);
printf("\ncharacters: %d | words: %d | sentences: %d | paragraphs: %d\n------------------------------------------------------------------------------------------------", car, word, sen, par);
//checks if the user wants to continue or exit
char answer;
printf("\n\nIf you want to clean another string press (y): ");
scanf_s(" %c", &answer, 1);
if (answer != 'y') {
stop = YES;
}
else {
(void)getchar();
printf("\n");
}
}
printf("\nGoodbye!");
}
Here is an example for a text that creates this problem:
"mechanics is , IN the most general sense , the study of forces and their effect upon matter. typically , Engineering mechanics is used to analyze and predict the acceleration and deformation (both elastic and plastic) of objects under known forces (also called loads) or stresses . subdisciplines of mechanics include.. statics, the study of non-moving bodies under known loads, how forces affect static bodies..Dynamics the study of how forces affect moving bodies. Dynamics includes kinematics (about movement, velocity, and acceleration) and kinetics.
n"
I am getting an int of the entire string s for 'letter', the conditions in my 'if' statement seem to not be reading properly - is my syntax incorrect?
I get user input:
string s = get_string("Text here: ");
the function is as follows:
int letter_count(string s)
{
int i =0;
int len = strlen(s);
int letter = 0;
while(i < len)
{
if (s[i] != '\0' || s[i] != '.' || s[i] != ',' || s[i] != '!' || s[i] != '?')
{
letter++;
}
i++;
}
return letter;
}
then call the function:
int letter = letter_count(s);
printf("letter Count: %i\n", letter);
Try changing the OR operator with the AND
if (s[i] != '\0' || s[i] != '.' || s[i] != ',' || s[i] != '!' || s[i] != '?')
is ALWAYS true. Because any character is either not "." or not ",". Which letter would you expect to be both?
You want to check whether the current letter is "not ." AND "not ," AND "not !".
I.e.
if (s[i] != '\0' && s[i] != '.' && s[i] != ',' && s[i] != '!' && s[i] != '?')
Almost correct, you have to change the type of the argument to char*, there is no string type on the default libraries. (Documentation of string library).
Working example with the modifications:
#include <stdio.h>
#include <string.h>
int letter_count (char* s)
{
int i = 0;
int len = strlen (s);
int letter = 0;
while (i < len)
{
if (s[i] != '\0' && s[i] != '.' && s[i] != ',' && s[i] != '!'
&& s[i] != '?')
{
letter++;
}
i++;
}
return letter;
}
int main ()
{
char my_word[] = "Sample word";
printf ("'%s' have %d letters",my_word, letter_count (my_word));
return 0;
}
Output:
'Sample word' have 11 letters
The code below is meant to take an input string like My name is Smith and outputs
My
name
is
Smith
and also has to exclude things like: , . and space, just these three, but instead it outputs, I'm not allowed to use any thing like strlen or strtok
My
y
name
ame
me
e
is
s
Smith
mith
ith
th
h
I've searched for the error everywhere in the code and I can't seem to figure it out
int main()
{
int wordSize = 0;
char str[81];
char* ptr_to_word[81];
gets_s(str);
for (char* res_p = &(str[0]); *res_p != '\0'; res_p++) {
if ((*res_p != '.') || (*res_p != ',') || (*res_p != ' '))
{
ptr_to_word[wordSize] = res_p;
wordSize++;
}
}
if (wordSize == 0)
{
printf("no solution");
}
else
{
for (int i = 0; i < wordSize; i)
{
char* a = ptr_to_word[i];
while ((*a != '.') && (*a != ',') && (*a != ' ') && (*a != '\0'))
{
printf("%c", *a);
a++;
}
printf("\n");
}
}
return 0;
}
In the condition of the if statement within this loop
for (char* res_p = &(str[0]); *res_p != '\0'; res_p++) {
if ((*res_p != '.') || (*res_p != ',') || (*res_p != ' '))
{
ptr_to_word[wordSize] = res_p;
wordSize++;
}
}
you have to use the logical AND operator instead of the logical OR operator like
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' '))
Nevertheless the loop in any case is wrong because the variable wordSize does not count words but counts each character that is not equal to the characters listed in the if statement.
To output separate words there is no need to declare an array of pointers to starts of words. You can output each word as soon as its start is found.
Here is a very simple demonstrative program.
#include <stdio.h>
int main(void)
{
enum { N = 81 };
char s[N];
fgets( s, N, stdin );
for ( const char *p = s; *p; )
{
int wordSize = 0;
while ( *p && *p != '.' && *p != ',' && *p != ' ' && *p != '\t' && *p != '\n' )
{
++wordSize;
++p;
}
if ( wordSize )
{
printf( "%.*s\n", wordSize, p - wordSize );
}
else
{
++p;
}
}
return 0;
}
If to input "My name is Smith" then the program output might look like
My
name
is
Smith
I appended the list of delimiters with the tab character '\t' and the new line character '\n' that can be inserted in the input string by the function fgets.
First of all, this condition
if ((*res_p != '.') || (*res_p != ',') || (*res_p != ' ')
will always be true, think about it, *res_p is always not '.' OR not ','. However, if you change the operator to && your code will still produce the same result.
The first loop with || operator writes a pointer to every character in your input string to the array ptr_to_word, and ' 's and '.'s are not printed only because of a condition in the second loop.
If you change the operator to && like so,
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' ')
you will write all the pointers, except for the '.', ',' and ' ', into the array, e.g. ptr_to_word[0] will point to 'My name is Smith', ptr_to_word[1] to 'y name is Smith', etc.
I have made a few changes to your code so that it would work as intended.
void split_str(char *str)
{
int wordSize = 0;
char *ptr_to_word[81];
char *res_p = &(str[0]);
int i = 0;
for (; *res_p != '\0'; res_p++) {
if ((*res_p != '.') && (*res_p != ',') && (*res_p != ' '))
{
wordSize++;
}
else
{
ptr_to_word[i] = res_p - wordSize;
wordSize = 0;
i++;
}
}
ptr_to_word[i] = res_p - wordSize;
ptr_to_word[i + 1] = NULL;
if (i == 0)
{
printf("no solution\n");
}
else
{
for (int i = 0; ptr_to_word[i]; i++)
{
char* a = ptr_to_word[i];
while ((*a != '.') && (*a != ',') && (*a != ' ') && (*a != '\0'))
{
printf("%c", *a);
a++;
}
printf("\n");
}
}
}
int main() {
split_str("My name is Smith\n");
}
This way you are writing a new value to the pointer array only when dot, comma or a space is encountered. For all other chars, you just do wordSize++ to keep track of the length of the word. I used pointer arithmetic to move back to the start of the word (ptr_to_word[i] = res_p - wordSize;).
I have tried to make only minimal changes to your code, just enough to make it work. There are still things I would change to make it better, e.g. the first loop finishes when the '\0' is encountered. Most likely, the last word finishes with a '\0', not a '.' or a ' '. Thus, it won't be written to the ptr_to_word, and I had to manually write it after the loop. Also, you don't even need two loops, you can use the same pointer. arithmetic to output the word as soon as it is found. So I'd advise you to do. a self-code-review, and optimize it further.
Good luck!
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"
The program should print the number of empty lines and certain operators from the input text. I got the problem of empty lines fixed but I'm facing issues with the opperators. I guess it is something wrong with the break. I would appreciate any good ideas for fixing the code. Sorry if such a thread already exists but I checked and couldn't get a solution. Thanks in advance!
char c,line[300];
int emptyLine = 0;
int operators = 0;
printf("Input your text and press ctr+Z on a new line when done: \n");
while(gets(line)) {
int i = 0;emptyLine++;
for (i = 0; i < strlen(line); i++) {
if(line[i] == '+'|| line[i] == '-' || line[i] == '/' || line[i] == '*' || line[i] == '%')
{
operators++;
}
if (line[i] != '\n' && line[i] != '\t' && line[i] != ' ') {
emptyLine--;
break;
}
}
}
printf("The number of empty lines is: %d",emptyLine);
printf("\nThe number of opperators is: %d",operators);
Try something like this:
char c,line[300];
int emptyLine = 0;
int operators = 0;
printf("Input your text and press ctr+Z on a new line when done: \n");
while(gets(line)) {
bool isEmpty = true; // Assume empty line
for (int i = 0; 0 != line[i]; i++) {
if (!isspace(line[i])) {
isEmpty = false; // Line not empty
}
if (line[i] == '+'|| line[i] == '-' || line[i] == '/' || line[i] == '*' || line[i] == '%') {
operators++;
}
}
if (isEmpty) {
emptyLine += 1;
}
}
printf("The number of empty lines is: %d",emptyLine);
printf("\nThe number of operators is: %d",operators);