I have this program that receives a char array with a number of messages bounded by tags. These "tags" are a sequence of chars located randomly within the char array.
Here is an example: given a char array: {'a','s','t','1','m','s','g','e','x','1','r','s','t','1','s','t','1','s','s','g','e','x','1','z'};. the tag "st1" indicates the beginning of a message which contains every char until a sequence of "ex1" is found, which is a tag for the end of the message, and it keeps searching the array for the next sequence of "st1" indicating the beginning of a new message. In this example, the messages are: "msg",and"st1ssg".
Here is my program - I keep getting a segmentation fault:
int main(int argc, char const *argv[])
{
char array[] = {'a','s','t','1','m','s','g','e','x','1','r','s','t','1','s','t','1','s','s','g','e','x','1','z'};
int state = 0;
int found = 0;
int i,j;
int msgStartIndex;
int msgEndIndex;
while(array[i]){
if((array[i] == 's' && state == 0) || (array[i] == 't' && state == 1) || (array[i] == '1' && state == 2) ){
state++;
if(!found && state == 3){
msgStartIndex = i+1;
found = 1;
}
}
else if(!found && (array[i] = 't' && state == 2))
state = 2;
else if(!found)
state = 0;
if((array[i] == 'e' && state == 3) || (array[i] == 'x' && state == 2) || (array[i] == '1' && state == 1) ){
state--;
if(found && state == 0){
found = 0;
msgEndIndex = i-3;
for(j=msgStartIndex; j < msgEndIndex+1; j++)
printf("%c",array[j]);
printf("\n");
}
}
else if(found && (array[i] == 'e' ) && (state == 2 || state == 1))
state = 2;
else if(found)
state = 3;
i++;
}
return 0;
}
You never bothered initializing your loop counter:
int i,j;
while(array[i]){
so you just start using whatever random garbage is in i to begin with. If that garbage happens to be bigger than the length of the array, boom goes your program.
Variable I was notr initialized and moreover the array is not zero-terminated.
int i,j;
/...
while(array[i]){
So the loop has undefined behavior.
You could keep a string in the array and use standard function strstr declared in header <string.h> to find the starting and ending tags.
Related
This is my palindrome code in c:
#include <stdio.h>
#include <stdlib.h>
char toUpperCase(char c) {
if (c > 'Z') {
c -= 32;
}
return c;
}
int isPalindrom(char word[40]) {
int count = 0;
int letterCount = 0;
char lettersOnly[40];
for (int i = 0; i < 40; i++) {
char current = word[i];
if (current == '\n' || current == '\0') {
count = i;
break;
}
if ((current >= 'A' && current <= 'Z') || (current >= 'a' && current <= 'z')) {
lettersOnly[letterCount] = current;
letterCount++;
}
}
return 1;
}
It gives me an error that I set the variable "count" but didn't use it. I clearly used it tho.
How can I resolve this?
Your code only sets the value of count (count = i in the loop). It never reads this value, and thus it's safe to say that the program would have worked the same way had it been removed altogether.
I just started learning C. I am supposed to create a password program where the user inputs strings that are at least 8 characters longs. It also needs to have one upper case, one lower case, one digits, and one symbol from this set {#, %, +}. I can't try to figure out the loop where it prints invalid when the user doesn't type in at least 8 characters. I tried using strlen but it gives me an error passing argument 1 of ‘strlen’ makes pointer from integer without a cast can someone help me?
#include <stdio.h>
#include <string.h>
int main()
{
int n;
int k;
char ch;
unsigned char uFlag = 0, cFlag = 0, dFlag = 0, hFlag = 0, aFlag = 0;
printf("Enter a password: ");
ch = getchar();
n = strlen(ch);
k = n - 1;
while (ch != '\n')
{
if(ch >= 'A' && ch <= 'Z')
uFlag = 1;
else if(ch >= 'a' && ch <= 'z')
cFlag = 1;
else if(ch >= '0' && ch <= '9')
dFlag = 1;
else if(ch == '#' || ch == '%' || ch == '+')
hFlag = 1;
else if (k >= 8)
aFlag = 1;
ch = getchar();
}
if (uFlag == 1 && cFlag == 1 && dFlag == 1 && hFlag == 1 && aFlag == 1)
{
printf("Password entered is valid.\n");
}
else
{
printf("Password entered is invalid.\n");
}
return 0;
}
char ch; defines a variable for a single character, not for a string. So you cannot use strlen(ch), because strlen expects a pointer to a string (and not a single character).
As you are reading in one character after another with ch = getchar() in a loop, you actually do not compose any string. The only thing you need to do is increment k with each iteration:
k = 0;
while (ch != '\n')
k++;
...
ch = getchar();
}
You must be used an array of characters and not an char. In your code, you have written -
n = strlen(ch);
However, strlen() accepts char* or an array of character or pointer to a string as parameter. You are passing ch which is of type char and is the wrong parameter data type. This is main reason why you are getting the error.
I have made minor edits in your program which you can refer below -
#include <stdio.h>
#include <string.h>
int main()
{
int i=0; //i to maintain current index in char array-ch
char ch[100],c; //or you could use dynamic allocation by asking user for input, c will read user input
unsigned char uFlag = 0, cFlag = 0, dFlag = 0, hFlag = 0, aFlag = 0;
printf("Enter a password: ");
c = getchar(); //read the input into character as you did
ch[i]=c; //assign the character to current index in ch array
while (ch[i] != '\n') //check until user hits enter
{
if(ch[i] >= 'A' && ch[i] <= 'Z')
uFlag = 1;
else if(ch[i] >= 'a' && ch[i] <= 'z')
cFlag = 1;
else if(ch[i] >= '0' && ch[i] <= '9')
dFlag = 1;
else if(ch[i] == '#' || ch[i] == '%' || ch[i] == '+')
hFlag = 1;
//the below should be if and not if else as in your posted code for it to work as expected
if (i >= 8) // sets the flag once length of array get over 8
aFlag = 1;
i++; // first increment index since we have already read at current index
c = getchar(); //same as before
ch[i] = c;
}
if (uFlag == 1 && cFlag == 1 && dFlag == 1 && hFlag == 1 && aFlag == 1)
{
printf("Password entered is valid.\n");
}
else
{
printf("Password entered is invalid.\n");
}
return 0;
}
Hope this solves your problem !
regarding:
ch = getchar();
n = strlen(ch);
the function getchar() only inputs a single char, not a string.
the function strlen() expects a NUL terminated array of characters.
Suggest inputting the password using;
fgets( buffer, sizeof( buffer ), stdin );
rather than using many calls to getchar()
then use:
buffer[ strcspn( buffer, "\n" ) ] = '\0';
to remove an newline character
then looping through the buffer[], checking each character
for( size_t i=0; buffer[i]; i++ )
{
// perform all the needed checks of the password
}
I'm trying to pass back an updated char array to the original main() function, however when i try to copy over the array with a pointer before it it gives me "Char " differs in levels of indirection from char() [15]'
This is a ISBN validator program.
Here it is:
int main(void)
{
int divisible;
char choice, trash;
char code[15];
do
{
printf("Enter an ISBN (book) number:\n");
fgets(code, 15, stdin);
printf("The ISBN entered is:%s\n", code);
divisible = testISBN(&code);
if (divisible == 1)
printf("\n\n\tValid ISBN Number\n");
else
printf("\n\n\tInvalid ISBN Number\n");
printf("\nDo you wish to continue? (Y/N)\n");
choice = getchar();
trash = getchar();
} while (toupper(choice) != 'N');
return 0;
}
int testISBN(char *code)
{
int i;
int sum = 0;
int weight = 10;
char codefinal[10];
int x = 0;
for (i = 0; i<15; i++)
{
int chVal;
if ((i == 9) && (toupper(code[i]) == 'X'))
{
printf("%c",code[i]);
chVal = 10;
}
else
{
chVal = code[i] - '0';
}
if (chVal == 0 || chVal == 1 || chVal == 2 || chVal == 3 || chVal == 4 || chVal == 5 || chVal == 6 || chVal == 7 || chVal == 8 || chVal == 9) {
char y = (char)chVal;
codefinal[x] = y;
x++;
}
sum += chVal * weight;
weight--;
}
printf("sum is %d", sum);
for (i = 0; i < 15; i++) {
*code[i] = codefinal[i];
printf("%c", code);
}
return (sum % 11) == 0;
}
At the very bottom where i said *code[i] = codefinal[i] is where i get the issue. I'm just trying to pass back by pointer my new updated array of numbers to my main.
Do following changes in your code:
Change prototype of function int testISBN(char* code) to int testISBN(char code[])
Change calling from testISBN(&code); to testISBN(code);
Change line *code[i] = codefinal[i]; to code[i] = codefinal[i];
In line printf("%c", code); you are printing not the value but the address of code[]. So change it to printf("%c", code[i]);. Note that code[] contains some non printable characters also.
Suggestion: You can change line if (chVal == 0 || chVal == 1 || chVal == 2 || chVal == 3 || chVal == 4 || chVal == 5 || chVal == 6 || chVal == 7 || chVal == 8 || chVal == 9) to if((chVal >= 0) && (chVal <= 9)) for simplicity.
Just pass code as is it will decay into pointer.
char code[15];
divisible = testISBN(code);
You may want to change testISBN signature to
int testISBN(char code[15]);
This way you have a higher chances to get compiler warning if you mess up indices.
Simple example:
#include <stdio.h>
void func(char arr[3]) {
arr[0] = 'H';
arr[1] = 'i';
arr[2] = 0;
}
int main() {
char arr[3] = {0};
func(arr);
printf("%s", arr);
}
Prints "Hi"
As commenters mentioned your code has other issues such as memory out of bounds access. To ease your life spend some time with your compiler's manual and learn how to turn on all the warnings, they indicate code issues most of the time.
I am trying to find the most efficient way to find tags in a given char array. These "tags" are a sequence of chars located randomly within a char array.
Here is an example: given a char array: {'a','s','s','1','m','s','g','e','x','x','r','s','1',...}. the tag "ss1" indicates the beginning of a message which contains every char until a sequence of "exx" is found, which a tag for the end of the message, and it keeps searching the array for the next sequence of "s1". In this example, the message here is "msg".
my initial design was (pseudo code)
while(array[i] != '\0')
if(array[i] == 's' && array[i+1] == 's' && array[i+2] == '1' )
int j = i+3;
if(array[j] != '\0' && array[j] == 'e' && array[j+1] == 'x' && array[j+2] == 'x' )
i += 3;
else
print(array[j]);
else i++; //next char
may be a little flawed, but you get the idea. Is there a better way? i thought about strstr but since I'm dealing with a char array here and still looping even after deciphering a message, I thought it might be difficult to implement.
Try to maintain a state denoting how much of the tag start and end you have found. Something like this: (This code will work even if the message within the tag is of arbitrary length)
int state = 0;
int found = 0;
int i = 0,j;
int msgStartIndex;
int msgEndIndex;
while(array[i]){
if((array[i] == 's' && state == 0) || (array[i] == 's' && state == 1) || (array[i] == '1' && state == 2) ){
state++;
if(!found && state == 3){
msgStartIndex = i+1;
found = 1;
}
}
else if(!found && (array[i] = 's' && state == 2))
state = 2;
else if(!found)
state = 0;
if((array[i] == 'e' && state == 3) || (array[i] == 'x' && state == 2) || (array[i] == 'x' && state == 1) ){
state--;
if(found && state == 0){
found = 0;
msgEndIndex = i-3;
for(j=msgStartIndex; j < msgEndIndex+1; j++)
printf("%c",array[j]);
printf("\n");
}
}
else if(found && (array[i] == 'e') && (state == 2 || state == 1))
state = 2;
else if(found)
state = 3;
i++;
}
Updated answer for start tag st1 and end tag ex1
int state = 0;
int found = 0;
int i=0,j;
int msgStartIndex;
int msgEndIndex;
while(array[i]){
if((array[i] == 's' && state == 0) || (array[i] == 't' && state == 1) || (array[i] == '1' && state == 2) ){
state++;
if(!found && state == 3){
msgStartIndex = i+1;
found = 1;
}
}
else if(!found && (array[i] = 's' && (state == 1 || state == 2)))
state = 1;
else if(!found)
state = 0;
if((array[i] == 'e' && state == 3) || (array[i] == 'x' && state == 2) || (array[i] == '1' && state == 1) ){
state--;
if(found && state == 0){
found = 0;
msgEndIndex = i-3;
for(j=msgStartIndex; j < msgEndIndex+1; j++)
printf("%c",array[j]);
printf("\n");
}
}
else if(found && (array[i] == 'e') && (state == 2 || state == 1))
state = 2;
else if(found)
state = 3;
i++;
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 ...