C - Can't add to or call specific array? - c

My program takes two parameters eg "./a abc xyz" where all a's in a text file are replaced with x's and b's with y's and so on. When given a range, eg. A-C, it reads it as ABC.
The issue I am having is that when I add chars to a certain array(alphaRange2) I get a segmentation fault when I run it. I use the same code for array alphaRange1, which does accept the chars as shown when I print alphaRange1 in a for loop. When I try to print alphaRange2, no values are printed.
Here's my code:
int translate(char set1[], char set2[]) {
int c;
char ch;
char ch2;
int dash1 = 0;
int dash2 = 0;
int previous = -1;
int next;
char alphaRange1[MAXSIZE];
char alphaRange2[MAXSIZE];
size_t i;
int j = 0;
int k;
int l;
for (i=0; i <= strlen(set1); i++) {
if (set1[i] == '-') {
for (ch = set1[i-1]; ch <= set1[i+1]; ch++) {
alphaRange1[k] = ch;
k++;
}
}
}
for (i=0; i <= strlen(set2); i++) {
if (set2[i] == '-') {
for (ch = set2[i-1]; ch <= set2[i+1]; ch++) {
alphaRange2[l] = ch;
l++;
}
}
}
/*for (i=0; alphaRange1[i] != '\0'; i++) {
printf("%c", alphaRange1[i]);
}*/
while ((c = getchar()) != EOF) {
if ((dash1 == 1) && (dash2 == 1)) {
for (i=0; alphaRange1[i] != '\0' || alphaRange2[i] != '\0'; i++) {
if (c == alphaRange1[i]) {
c = alphaRange2[i];
}
}
} else if ((dash1 == 0) && (dash2 == 0)) {
for (i=0; i <= strlen(set1) || i <= strlen(set2); i++) {
if (c == set1[i]) {
c = set2[i];
if ((c == set1[1]) && (set1[1] == set2[0])) {
c = set2[0];
break;
}
}
}
}
if (previous > -1) {
putchar(previous);
}
previous = c;
}
putchar('\n');
return 1;
}
int main(int argc, char *argv[]) {
int i, j, k;
char set1[MAXSIZE];
char set2[MAXSIZE];
char ch;
char alphaRange1[MAXSIZE];
for (i=0; i < argc; i++) {
for (j=0; argv[1][j] != '\0' || argv[2][j] != '\0'; j++) {
set1[i] = argv[1][i];
set2[i] = argv[2][i];
}
}
/*for (i=0; i <= strlen(set1); i++) {
if (set1[i] == '-') {
for (ch = set1[i-1]; ch <= set1[i+1]; ch++) {
alphaRange1[k] = ch;
k++;
}
}
}
for (i=0; alphaRange1[i] != '\0'; i++) {
printf("%c", alphaRange1[i]);
}*/
translate(set1, set2);
return 1;
}
The code runs if you take out anything including alphaRange2, and I've been testing it using commented out print loop, which works if you comment out the entire while loop. How do I make this work?
Thanks.

Related

String Pattern Matching in C

I was trying this pattern matching method in C but whenever I give all the input, the vscode terminal waits for a while and just stops the program without any warnings/message. Can anyone point to what is wrong here?
#include <stdio.h>
#include <string.h>
int main()
{
char STR[100], PAT[100], REP[100], ANS[100];
int i, m, j, k, flag, slP, slR, len;
i = m = k = j = flag = len = 0;
printf("\nMain String: ");
gets(STR);
printf("\nPattern String: ");
gets(PAT);
slP = strlen(PAT);
printf("\nReplace String: ");
gets(REP);
slR = strlen(REP);
while (STR[i] != '\0')
{
if (STR[i] = PAT[j])
{
len = 0;
for (k = 0; k < slP; k++)
{
if (STR[k] = PAT[k])
len++;
}
if (len == slP)
{
flag = 1;
for (k = 0; k < slR; k++, m++)
ANS[m] = REP[k];
}
}
else
{
ANS[m] = STR[i];
m++;
i++;
}
}
if (flag == 0)
{
printf("\nPattern not found!");
}
else
{
ANS[m] = '\0';
printf("\nResultant String: %s\n", ANS);
}
return 0;
}
There are multiple problems in the code:
using gets() is risky, this function was removed from the C Standard because it cannot be used safely.
if (STR[i] = PAT[j]) copied the pattern to the string. You should use:
if (STR[i] == PAT[j])
similarly, if (STR[k] = PAT[k]) is incorrect. You should compare PAT[k] and STR[i + k]:
if (STR[i + k] == PAT[k])
you should test for buffer overflow for the output string as replacing a short string by a larger one may produce a string that will not fit in ANS
you do not increment i properly.
Here is a modified version:
#include <stdio.h>
int getstr(const char *prompt, char *dest, int size) {
int c, len = 0;
printf("%s", prompt);
while ((c = getchar()) != EOF && c != '\n') {
if (len + 1 < size)
dest[len++] = c;
}
if (size > 0)
dest[len] = '\0';
printf("\n");
if (c == EOF && len == 0)
return -1;
else
return len;
}
int main() {
char STR[100], PAT[100], REP[100], ANS[100];
int i, m, k, flag;
if (getstr("Main String: ", STR, sizeof STR) < 0)
return 1;
if (getstr("Pattern String: ", PAT, sizeof PAT) < 0)
return 1;
if (getstr("Replace String: ", REP, sizeof REP) < 0)
return 1;
i = m = flag = 0;
while (STR[i] != '\0') {
if (STR[i] == PAT[0]) { // initial match
// compare the rest of the pattern
for (k = 1; PAT[k] != '\0' && PAT[k] == STR[i + k]; k++)
continue;
if (PAT[k] == '\0') { // complete match
flag = 1;
// copy the replacement string
for (k = 0; REP[k] != '\0'; k++) {
if (m + 1 < sizeof ANS)
ANS[m++] = REP[k];
}
i += k; // skip the matching characters
continue;
}
}
// otherwise copy a single character
if (m + 1 < sizeof ANS)
ANS[m++] = STR[i];
i++;
}
ANS[m] = '\0';
if (flag == 0) {
printf("Pattern not found!\n");
} else {
printf("Resultant String: %s\n", ANS);
}
return 0;
}

Trying to print 'X' pattern string

Below is my final code but no output has been printed in the console. Please help me to find the mistake.
#include<stdio.h>
#include<string.h>
int main()
{
char s[10] = "Gokul";
int len = 0;
while(s[len] != '\0');
len++;
for(int i = 0; i < len; i++){
for(int j = 0; j < len; j++){
if(j==i || j == (len-i-1)){
printf("%c", s[i]);
}
else printf(" ");
}
printf("\n");
}
return 0;
}
while(s[len] != '\0');
len++;
Mistake is here.
The body of your loop is empty
Next time, use a debugger.
The meaning of the statement
while(s[len] != '\0');
is
while (s[len] != '\0') {
}
So in your case the statement
while (s[len] != '\0');
len++;
will be expanded to
while (s[len] != '\0') {
}
len++;
which is wrong based on the logic.
The len++; statement should come inside the while condition.
So either you can use like below
while (s[len] != '\0')
len++;
or
while (s[len] != '\0') {
len++;
}
So I am pasting the working code here
#include<string.h>
int main() {
char s[10] = "Gokul";
int len = 0;
while (s[len] != '\0') {
len++;
}
printf("len=%d\n", len);
for (int i = 0; i < len; i++) {
for (int j = 0; j < len; j++) {
if (j == i || j == (len - i - 1)) {
printf("%c", s[i]);
} else printf(" ");
}
printf("\n");
}
return 0;
}
Hope this helps you.

passing char array to function from scanf in c

I have following function in c code
void analyze_text(char text[]) {
...
for (int i = 0; i < text_length || text[i] != '\0'; i++) {
...
}
}
In main function i would like to pass some string to it. If i do something like this
char text[4000] = "some text here";
analyze_text(text);
this is cool and do the goal, but i would like to have some user input present and I am not sure how to get char[] out of it. I tried following 2 and none of them seemed to work:
char text[4000];
scanf("%s",text);
analyze_text(text);
OR
char text[4000];
int c;
int count=0;
c = getchar();
count = 0;
while ((count < 4000) && (c != EOF)) {
text[count] = c;
++count;
c = getchar();
}
analyze_text(text);
I know that the first one should return pointer to char array, but second one should return char array itself, or not?
Its been like 10 years since i havent been working with c/c++. Can anybody give me some hint please?
update (whole function):
void analyze_text(char text[]) {
int printable_text_length = 0;
int text_length = strlen(text);
int word_count = 0;
int sentence_count = 0;
int in_sentence = 0;
int in_word = 0;
int count[ASCII_SIZE] = { 0 };
for (int i = 0; i < text_length || text[i] != '\0'; i++) {
int c = text[i];
if (!isspace(c)) {
printable_text_length++;
}
if (isalpha(c)) {
in_word = 1;
in_sentence = 1;
count[tolower(c)]++;
}
if (text[i] == ' ' && text[i + 1] != ' ' && in_word==1) {
word_count++;
in_word = 0;
}
if (text[i] == '.' && in_sentence==1) {
sentence_count++;
in_sentence = 0;
}
}
if (in_word == 1) { word_count++; }
if (in_sentence == 1) { sentence_count++; }
char charIndexes[ASCII_SIZE];
for (int i = 97; i <= 122; i++) {
charIndexes[i] = i;
}
for (int i=97; i <= 122; i++) {
for (int j = i + 1; j <= 122; j++) {
if (count[i] > count[j]) {
int temp = count[j];
count[j] = count[i];
count[i] = temp;
int temp2 = charIndexes[j];
charIndexes[j] = charIndexes[i];
charIndexes[i] = temp2;
}
}
}
...printf...
}
The issue with
char text[4000];
scanf("%s",text);
analyze_text(text);
is that scanf identifies space-separated chunks, so you'll only read the first one.
In order to read up to a whole line from the user, try fgets:
char text[4000];
fgets(text, 4000, stdin);
analyze_text(text);
You may want to check the return value of fgets for error detection.
You can use dyanamic array of char to pass it into the function.
Here is the code
#include <stdio.h>
#include <stdlib.h>
void analyze_text(char* text) {
for (int i = 0; text[i] != '\0'; i++) {
printf("%c\n",text[i] );
}
}
int main() {
char* text = (char *)malloc(4000 * sizeof(char));
scanf("%s", text);
analyze_text(text);
return 0;
}
and here is the output with input = 'abhishek'
a
b
h
i
s
h
e
k
remember that strlen in dyanamc array will not give the length of input array.

How can I get my Lexical analyzer program to print out more than just seperators?

Im writing a Lexical analyzer to read from a file and describe the text as either identifiers, keywords, separators, or operators. For some reason I am only able to output the separators, unless I delete or comment out the while loop with the print statement for the separators. When I delete that, the program prints out everything else correctly, skipping over the separators.
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<ctype.h>
int isKeyword(char buffer[]){
char keywords[32][10] = {"auto","break","case","char","const","continue","default",
"do","double","Else","enum","Function","Float","for","goto",
"If","Integer","long","register","Return","short","signed",
"sizeof","static","struct","switch","typedef","union",
"DOWhile","void","Write","while"};
int i, flag = 0;
for(i = 0; i < 32; ++i){
if(strcmp(keywords[i], buffer) == 0){
flag = 1;
break;
}
}
int k, flag2 = 0;
for (k = 0; k<32; ++k){
if(strcmp(keywords[i], buffer) == 0){
flag2 = 1;
break;
}
}
return flag;
return flag2;
}
int main(){
char ch, buffer2[15], operators[] = "+-*/%=";
char ch2, buffer[15], seperators[] = "{}(),;";
FILE *fp;
int i,k,j=0;
fp = fopen("input.txt","r");
if(fp == NULL){
printf("error while opening the file\n");
exit(0);
}
while((ch = fgetc(fp)) != EOF){
for(i = 0; i < 6; ++i){
if(ch == operators[i])
printf("%c is operator\n", ch);
while((ch2 = fgetc(fp)) != EOF){
for(k = 0; k < 6; ++k){
if(ch2 == seperators[k])
printf("%c is seperator\n", ch2);
}
}
if(isalnum(ch)){
buffer[j++] = ch;
}
else if((ch == ' ' || ch == '\n') && (j != 0)){
buffer[j] = '\0';
j = 0;
if(isKeyword(buffer) == 1)
printf("%s is keyword\n", buffer);
else
printf("%s is indentifier\n", buffer);
}
}
}
fclose(fp);
return 0;
}
The problem seems to be the second while loop containing the separator instructions, but I cant seem to figure out how to print that along with everything else.
I think this may help.There is no reason to create an additional char ch, or the buffer, when creating the separators. Just add it onto the end of the previous line. I just split it with a comma.This will clean your code up and allow you to keep the separators with the rest of the while loop code.
#include <stdio.h>
#define KEY 32
#define BUFFER_SIZE 15
int isKeyword(char buffer[])
{
char keywords[KEY][10] = { "auto","break","case","char","const","continue","default", "do","double","else","enum","extern","float","for","goto",
"if","int","long","register","return","short","signed", "sizeof","static","struct","switch","typedef","union", "unsigned","void","volatile","while"};
int i, flag = 0;
for (i = 0; i < KEY; ++i)
{
if (strcmp(keywords[i], buffer) == 0)
{
flag = 1;
break;
}
}
return flag;
}
int main()
{
char ch, buffer[BUFFER_SIZE], operators[] = "+-*/%=", separators[] = "(){}[]<>,";
FILE *fp;
int i, j = 0;
fp = fopen("Text.txt", "r");
while ((ch = fgetc(fp)) != EOF)
{
for (i = 0; i < 6; ++i)
{
if (ch == operators[i])
{
printf(" OPERATOR: %c \n", ch);
}
else if (ch == separators[i])
printf(" SEPARATOR: %c \n", ch);
}
if (isalnum(ch))
{
buffer[j++] = ch;
}
else if ((ch == ' ' || ch == '\n') && (j != 0))
{
buffer[j] = '\0';
j = 0;
{
if (isKeyword(buffer) == 1)
printf(" KEYWORD: %s \n", buffer);
else
printf(" IDENTIFIER: %s \n", buffer);
}
}
}
fclose(fp);
return 0;
}

replacing integers with strings in C

I wrote code that replaces integers from 0 to 3 with strings. I was only allowed to use getchar() and putchar(). If the input is 1, the output will become "one".
#include <stdio.h>
int main()
{
int c;
char* arr[4] = {"zero", "one", "two","three"};
int i;
while ((c = getchar ()) != EOF)
{
if(c==0+'0') {
char* str = arr[0];
for (i = 0; str[i] != '\0'; i++) {
putchar(str[i]);
}
}
else if(c==1+'0') {
char* str = arr[1];
for (i= 0; str[i] != '\0';i++) {
putchar(str[i]);
}
}
else if(c==2+'0') {
char* str = arr[2];
for (i = 0; str[i] != '\0'; i++) {
putchar(str[i]);
}
}
else if(c==3+'0') {
char* str = arr[3];
for (i = 0; str[i] != '\0'; i++) {
putchar(str[i]);
}
}
else
putchar(c);
}
return 0;
}
The code is pretty long. Is there a shorter way to write it?
If I type in 33 the output will be "threethree". Could anyone give me suggestions how can i modify my code not to do that?
note: I am also not allowed to use functions.
You can use a variable to remember last input and compare, so that you will not print continuous char.
#include <stdio.h>
int main()
{
int c;
char* arr[4] = {"zero", "one", "two","three"};
int i;
char last_input = '9';
while ((c = getchar ()) != EOF)
{
if(c != last_input && '0' <= c && c <= '3') {
last_input = c;
int index = c - '0';
char* str = arr[index];
for (i = 0; str[i] != '\0'; i++) {
putchar(str[i]);
}
}
else{
putchar(c);
}
}
return 0;
}
You can compress your if statements using one if condition like this :
#include <stdio.h>
int main()
{
int c;
char* arr[4] = {"zero", "one", "two","three"};
int i;
while ((c = getchar ()) != EOF) {
int k = c-'0';
if(k>=0 && k<=3) {
char* str = arr[k];
for (i= 0; str[i] != '\0';i++) {
putchar(str[i]);
}
}
else {
putchar(c);
}
}
return 0;
}
Here is the simple approach to the same task. I tried to explain the logic in the comments.
int main(void) {
char *arr[11] = {"zero", "one", "two","three","four","five","six","seven","eight","Nine","Ten"};
int *input = malloc(sizeof(*input))/*1st time 4 byte */ , row = 1;
while( (input[row-1] = getchar())!=EOF ) {
if(input[row-1]==10) /* if ENTER key is presed */
break;
input[row-1] = input[row-1] - 48;/* convert it */
printf("%s ",arr[ input[row-1]%10 ]);/* its simple, just think on it */
row++;
input = realloc(input,row * sizeof(*input));/* reallocate based on number of input */
}
/* free dynamically allocated memory #TODO*/
return 0;
}
I just given hint, make it generic like write the condition if input is less than zero etc. I hope it helps.
Here my code using loop to shorten your code.
#include <stdio.h>
int main()
{
int c;
char* arr[4] = {"zero", "one", "two","three"};
int i, j;
while ((c = getchar ()) != EOF)
{
for(j = 0; j < 4; j++)
{
if(c == j + '0')
{
char* str = arr[j];
for (i = 0; str[i] != '\0'; i++)
{
putchar(str[i]);
}
j = 10; // just to detect processed character
break;
}
}
if(j != 10)
{
putchar(c);
}
}
return 0;
}

Resources