This program is meant to sort words alphabetically, either words that are imputed into it, or from a text file. It compiles just fine, but when I run it, I get a large mass of text. Here is a small sample of it:
:*.dl=01;35:*.xcf=01;35:*.xwd=01;35:*.yuv=01;35:*.cgm=01;35:*.emf=01;35:*.axv=01;35:*.anx=01;35:*.ogv=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
v=01;35:*.ogx=01;35:*.aac=00;36:*.au=00;36:*.flac=00;36:*.mid=00;36:*.midi=00;36:*.mka=00;36:*.mp3=00;36:*.mpc=00;36:*.ogg=00;36:*.ra=00;36:*.wav=00;36:*.axa=00;36:*.oga=00;36:*.spx=00;36:*.xspf=00;36:
It kinda looks like some file formats or something?
This is followed by the words:
Segmentation fault (core dumped)
I'm compiling in GCC on Ubuntu.
The program is:
#include <stdio.h>
#include <string.h>
#define MO 109 // 109 is ASCII for "m".
#define FO 102 // 102 is ASCII for "f".
#define OO 101 // 101 is ASCII for "e" and denotes an error.
int main() // Main part of program.
{
int i, j; // Counter integer assignment.
int n = 100; // assignment of integer for the number of strings.
char a; // For the m/f (manual or file) option.
char str[100][100]; // Str is the main string to be sorted.
char temp[100]; // Temp is to switch the values for bubble sorting.
for(i = 0; i < 1; a = OO)
{
printf("To input text manually, press m. To sort a file, press f. \n");
// M/f option.
scanf("%c", &a); // Gets m/f option.
if(a == MO || a == FO) // Checks for valid input.
{
i = 2; // Escape from loop with valid input.
}
if(a != MO && a != FO) // Invalid input.
{
printf("Please insert a valid response. ");
i = 0; // Continue loop until a valid input is reached.
}
}
if(a == MO) // Manual insert option.
{
puts("Enter the number of strings to be sorted.");
scanf("%d", &n); // Gets number of strings.
for(i = 0; i <= n; i++)
{
gets(str[i]); // Gets strings from user.
}
}
if(a == FO) // File option.
{
char b[100]; // File address of text file to be sorted.
FILE * f; // Text file.
printf("Enter file path of file to be sorted.");
scanf("%c", b); // Gets file path.
f = fopen(b, "r"); // Opens file.
fgets(*str, 100, f); // Coverts file into string str.
fclose(f); // Closes file.
}
for(i = 0; i <= n; i++) // Begin bubble sort.
{
for(j = i + 1; j <= n; j++)
{
if(strcmp(str[i], str[j]) > 0) // Checks alphabetical value.
{
strcpy(temp, str[i]); // Switch two strings.
strcpy(str[i], str[j]);
strcpy(str[j], temp);
}
}
}
printf("The sorted string:");
for(i = 0; i <= n; i++)
{
puts(str[i]); // Prints final output.
}
return 0; // End of main.
}
A Google search told me that a segmentation fault usually means that I'm referring to a place in the memory that doesn't exist. But I couldn't find any advice on how to fix it, or even what the problem is specifically.
If someone could help me out with this I would really appreciate it. Thanks.
As one of the comments to your question says, there are many things wrong with the code...
For example
for(i = 0; i < 1; a = OO)
{
// ...
}
At the end of that loop, a == OO always, because you tell it to equal OO in the last part of the for statement. So all your work to set the value of a inside the 'loop' is wasted.
But getting back to the point of the question, about the seg-fault: You're right that it's caused by referring to memory that your program doesn't own. In your case, it's probably because of this:
int n = 100; // assignment of integer for the number of strings.
// ...
char str[100][100]; // Str is the main string to be sorted.
// ...
for(i = 0; i <= n; i++) // Begin bubble sort.
{
for(j = i + 1; j <= n; j++)
{
if(strcmp(str[i], str[j]) > 0) // Checks alphabetical value.
str[100] is beyond the limits of your array. An array with 100 elements will use indicies from 0 to 99. str[100] would access the '101st' element, which is out of bounds and thus can cause a seg fault.
I did a small modification to your algorithm and it works for me:
#include <stdio.h>
#include <string.h>
#define MO 109 // 109 is ASCII for "m".
#define FO 102 // 102 is ASCII for "f".
#define OO 101 // 101 is ASCII for "e" and denotes an error.
int main() // Main part of program.
{
int i, j; // Counter integer assignment.
int n = 100; // assignment of integer for the number of strings.
char a; // For the m/f (manual or file) option.
char str[100][100]; // Str is the main string to be sorted.
char temp[100]; // Temp is to switch the values for bubble sorting.
a = OO;
i=0;
while(i < 1)
{
printf("To input text manually, press m. To sort a file, press f. \n");
// M/f option.
scanf("%c", &a); // Gets m/f option.
if(a == MO || a == FO) // Checks for valid input.
{
i = 2; // Escape from loop with valid input.
}
if(a != MO && a != FO) // Invalid input.
{
printf("Please insert a valid response. ");
i = 0; // Continue loop until a valid input is reached.
}
}
if(a == MO) // Manual insert option.
{
puts("Enter the number of strings to be sorted.");
scanf("%d", &n); // Gets number of strings.
for(i = 0; i <= n; i++)
{
gets(str[i]); // Gets strings from user.
}
}
if(a == FO) // File option.
{
char b[100]; // File address of text file to be sorted.
FILE * f; // Text file.
printf("Enter file path of file to be sorted.");
scanf("%c", b); // Gets file path.
f = fopen(b, "r"); // Opens file.
fgets(*str, 100, f); // Coverts file into string str.
fclose(f); // Closes file.
}
for(i = 0; i < n; i++) // Begin bubble sort.
{
for(j = i + 1; j <= n; j++)
{
if(strcmp(str[i], str[j]) > 0) // Checks alphabetical value.
{
strcpy(temp, str[i]); // Switch two strings.
strcpy(str[i], str[j]);
strcpy(str[j], temp);
}
}
}
printf("The sorted string:");
for(i = 0; i < n; i++)
{
puts(str[i]); // Prints final output.
}
return 0; // End of main.
}
Related
My professor asked me to make a Codebreaker game in C. (User is breaking the code by guessing original code. original code is given as a cmd-line arg.After every attempt;(b, w): the number of correct colors in the correct positions (b) and the number of colors that are part of the code but not in the correct positions (w) are printed as Feedback.)Only standard input and output is allowed. I got it working, but the arrays Secret_Code2 and guess2 goes out of bounds. It has some strange behaviours like changing int variables causes changes in arrays even they are independent. I'm aware that C does not check array bounds, is there any improvements that i can make?
Here is my code;
#include <stdio.h>
#define Max_Attempts 12
char *Sectret_CODE = NULL;
int main(int argc,char **argv)
{
//Definitions
printf("Available Colors: (B)lue (G)reen (O)range (P)urple (R)ed (Y)ellow\n\n");
//Getting input and validating
if(argc != 2)
{
fprintf(stderr,"Invalid input\n");
return 1;
}
Sectret_CODE = argv[1];
int i = Max_Attempts;
int Won = 0;
while (i > 0 && !Won)
{
int b = 0, w = 0, t=0;
char guess[4];
char Sectret_CODE2[4];
char guess2[4];
printf("No. guesses left: %i\n",i);
printf("Enter Your Guess: ");
scanf("%s",guess);
//printf("%s",guess);
for(int j = 0; j < 4; j++)
{
//printf("%s,%s\n",Sectret_CODE2,guess2);
if(Sectret_CODE[j] == guess[j])
{
b++;
}
else
{
Sectret_CODE2[t] = Sectret_CODE[j];
guess2[t] = guess[j];
t++;
printf("%s,%s,%i\n",Sectret_CODE2,guess2,t);
}
}
int s = t;
//printf("%i",t);
Sectret_CODE2[t] = '\0' ;
guess2[t] = '\0' ;
if(b == 4)
{
printf("You Won\n");
Won = 1;
return 0;
}
else
{
for(int j = 0; j < s; j++)
{
for(int k = 0; k < s;k++)
if(Sectret_CODE2[j] == guess2[k])
{
w++;
break;
}
}
}
printf("Feedback: %i,%i\n",b,w);
i--;
}
if(!Won)
{
printf("You Lose!\n");
}
}
You aren't allocating space for the terminating null character in your character arrays. Each array needs to hold up to 4 values, plus a terminating null character. So you need to declare them to hold 4+1 = 5 characters. Otherwise writing the null character can write past the end of the arrays.
Also, inside your loop, you are attempting to print those arrays using printf with %s before null-terminating them. You need to null-terminate them, at the proper point, before printing them with %s.
I have a project assignment for class and this is what it wants (in C)
Description
Write a program that simulates the search-and-replace operation in a text editor. The program is to have
only three function calls in “main”. The first function prompts the user to type a string of less than 80
characters. It then prompts the user to type the search substring of 10 or fewer characters. Finally, it
prompts the user to type the replace substring of 10 or fewer characters.
The second call is the search-and-replace function, which replaces all occurences of the search
substring with the replace substring and creates a new string. If no occurrences are found, it returns the
original string. Theoretically, the new string could be 800 characters long (80 identical characters
replaced by 10 characters each). Your function must be able to handle overflow by using the “realloc”
function to extend the new string when necessary. (Start with an output string of 80 characters and
extend by 80 as necessary.) The search-and-replace function returns the address of the new string.
After the search-and-replace function returns, a print function prints the resulting string as a series of 80 character lines. If performs word-wrap. That is, a line can end only at a space. If there is no space in 80 characters, then print 79 characters and a hyphen, and continue on the next line.
Write each called function using good structured programming techniques. It is expected to call subfunctions as necessary.
Run the program at least three times:
a. First, run it with no substitutions in the original input.
b. Second, run it with two or more substitutions.
c. Finally, run it with substitutions that cause the output to be at least three lines, one of which
requires a hyphen.
//this is what I have. it works but for some reason it only prints the original string for question c. ?
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void meow();
void modify();
void print();
char r[10];
char str[80];
char s[10];
char ans[800];
int main() {
meow();
modify();
print();
return 0;
}
void meow() {
printf("\nEnter a string max 80 chars \n");
fgets(str, 80, stdin);
printf("\nEnter a search string max 10 chars \n");
fgets(s, 10, stdin);
printf("\nEnter a replace string max 10 chars \n");
fgets(r, 10, stdin);
}
void modify()
{
int i;
int j;
int c;
int m;
int k;
i = 0;
m = 0;
c = 0;
j = 0;
k = 0;
while ((str[c]) != '\0') {
//if (str[m] == s[i]) {
if (str[m] == s[i]) {
i++;
m++;
if (s[i] == '\0') {
for (k = 0; r[k] != '\0'; k++, j++) {
ans[j] = r[k];
i = 0;
c = m;
}
}
}
//}
else {
ans[j] = str[c];
j++;
c++;
m = c;
i = 0;
}
//}
ans[j] = '\0';
}
}
void print() {
int i, ansl;
ansl = strlen(ans);
if (ansl > 80) {
for (i = 0;i < 80;i++) {
printf("%c", ans[i]);
printf("-\n");
}
}
else {
printf("%s\n", ans);
}
}
I'm having trouble with trying to manipulate 2d dynamic arrays in C. What I want to do is to store a char string in every row of the the 2d array then perform a check to see if the string contains a certain character, if so remove all occurrences then shift over the empty positions. What's actually happening is I get an exit status 1.
More about the problem, for example if I have
Enter string 1: testing
Enter string 2: apple
Enter string 3: banana
I would want the output to become
What letter? a // ask what character to search for and remove all occurences
testing
pple
bnn
Here is my full code:
#include <stdio.h>
#include <stdlib.h>
void removeOccurences2(char** letters, int strs, int size, char letter){
// Get size of array
// Shift amount says how many of the letter that we have removed so far.
int shiftAmt = 0;
// Shift array says how much we should shift each element at the end
int shiftArray[strs][size];
// The first loop to remove letters and put things the shift amount in the array
int i,j;
for(i=0;i < strs; i++){
for(j = 0; j < size - 1; j++) {
if (letters[i][j] == '\0'){
break;
}
else {
// If the letter matches
if(letter == letters[i][j]){
// Set to null terminator
letters[i][j] = '\0';
// Increase Shift amount
shiftAmt++;
// Set shift amount for this position to be 0
shiftArray[i][j] = 0;
}else{
// Set the shift amount for this letter to be equal to the current shift amount
shiftArray[i][j] = shiftAmt;
}
}
}
}
// Loop back through and shift each index the required amount
for(i = 0; i < strs; i++){
for(j = 0; j < size - 1; j++) {
// If the shift amount for this index is 0 don't do anything
if(shiftArray[i][j] == 0) continue;
// Otherwise swap
letters[i][j - shiftArray[i][j]] = letters[i][j];
letters[i][j] = '\0';
}
//now print the new string
printf("%s", letters[i]);
}
return;
}
int main() {
int strs;
char** array2;
int size;
int cnt;
int c;
char letter;
printf("How many strings do you want to enter?\n");
scanf("%d", &strs);
printf("What is the max size of the strings?\n");
scanf("%d", &size);
array2 = malloc(sizeof(char*)*strs);
cnt = 0;
while (cnt < strs) {
c = 0;
printf("Enter string %d:\n", cnt + 1);
array2[cnt] = malloc(sizeof(char)*size);
scanf("%s", array2[cnt]);
cnt += 1;
}
printf("What letter?\n");
scanf(" %c", &letter);
removeOccurences2(array2,strs,size,letter);
}
Thanks in advance!
You can remove letters from a string in place, because you can only shorten the string.
The code could simply be:
void removeOccurences2(char** letters, int strs, int size, char letter){
int i,j,k;
// loop over the array of strings
for(i=0;i < strs; i++){
// loop per string
for(j = 0, k=0; j < size; j++) {
// stop on the first null character
if (letters[i][j] == '\0'){
letters[i][k] = 0;
break;
}
// If the letter does not match, keep the letter
if(letter != letters[i][j]){
letters[i][k++] = letters[i][j];
}
}
//now print the new string
printf("%s\n", letters[i]);
}
return;
}
But you should free all the allocated arrays before returning to environment, and explicitely return 0 at the end of main.
Well, there are several issues on your program, basically you are getting segmentation fault error because you are accessing invalid memory which isn't allocated by your program. Here are some issues I found:
shiftAmt isn't reset after processing/checking each string which lead to incorrect value of shiftArray.
Values of shiftArray only set as expected for length of string but after that (values from from length of each string to size) are random numbers.
The logic to delete occurrence character is incorrect - you need to shift the whole string after the occurrence character to the left not just manipulating a single character like what you are doing.
1 & 2 cause the segmentation fault error (crash the program) because it causes this line letters[i][j - shiftArray[i][j]] = letters[i][j]; access to unexpected memory. You can take a look at my edited version of your removeOccurences2 method for reference:
int removeOccurences2(char* string, char letter) {
if(!string) return -1;
int i = 0;
while (*(string+i) != '\0') {
if (*(string+i) == letter) {
memmove(string + i, string + i + 1, strlen(string + i + 1));
string[strlen(string) - 1] = '\0'; // delete last character
}
i++;
}
return 0;
}
It's just an example and there is still some flaw in its logics waiting for you to complete. Hint: try the case: "bananaaaa123"
Happy coding!
"...if the string contains a certain character, if so remove all occurrences then shift over the empty positions."
The original string can be edited in place by incrementing two pointers initially containing the same content. The following illustrates.:
void remove_all_chars(char* str, char c)
{
char *pr = str://pointer read
char *pw = str;//pointer write
while(*pr)
{
*pw = *pr++;
pw += (*pw != c);//increment pw only if current position == c
}
*pw = '\0';//terminate to mark last position of modified string
}
This is the cleanest, simplest form I have seen for doing this task. Credit goes to this answer.
I am creating a program where I insert a number of sentences and the program outputs them in order. I have finished the program, but when I run it it seems like the characters I input into the array aren't displayed or stored correctly, getting as a result random letters instead of the full sentence. Here is the code of the program:
char ch;
int i,j,k;
int nothing = 0;
int count = 1;
char lines[5][256];
int length[256];
int main() {
printf("Please insert up to a max of 5 lines of text (Press enter to go to next line and twice enter to stop the program):\n");
i = 0;
while (i<5){
j = 0;
ch = getche();
if (ch == '\r'){
if(i!= 0){
break;
}
printf("You have not inserted anything, please insert a line:");
i=-1;
}
if(ch != '\r'){
lines[i][j]=ch;
while (ch!='\r'){
ch = getche();
lines[i][j] = ch;
j++;
}
}
printf("\n");
i++;
}
for (k=i ; k > 0; k--){
printf("\tphrase %i :", count);
for ( j =0 ; j <= length[k]; j++){
printf("%c",lines[j][k]);
}
count++;
printf("\n");
}
return 0;
}
How can I get the characters to be stored and displayed correctly? Any help is appreciated, thank you!!
There are numerous problems with your code. I'll try and summarise here, and give you improved code.
Fist, some changes that I made to get this to compile on my system:
Changed getche() to getchar() (getche() does not appear to be available on Ubuntu).
I took out the section about re-entering a string, and just focused on the rest (since the logic there was slightly broken, and not relevant to your question). It will still check for at least one line though, before it will continue.
I had to change the check for \r to \n.
I changed your length array to size 5, since you'll only have the lengths of maximum 5 strings (not 256).
Some problems in your code:
You never updated the length[] array in the main while loop, so the program never knew how many characters to print.
Arrays are zero indexed, so your final printing loops would have skipped characters. I changed the for parameters to start at zero, and work up to k < i, since you update i after your last character in the previous loop. The same with j.
Your reference to the array in the printing loop was the wrong way around (so you would've printed from random areas in memory). Changed lines[j][k] to lines[k][j].
No need for a separate count variable - just use k. Removed count.
The nothing variable does not get used - removed it.
#include <stdlib.h>
#include <stdio.h>
char ch;
int i,j,k;
char lines[5][256];
int length[5];
int main()
{
printf("Please insert up to a max of 5 lines of text (Press enter to go to the next line and twice enter to stop the program):\n");
i = 0;
while (i<5)
{
j = 0;
ch = getchar();
if ((ch == '\n') && (j == 0) && (i > 0))
{
break;
}
if (ch != '\n')
{
while (ch != '\n')
{
lines[i][j] = ch;
j++;
ch = getchar();
}
}
length[i] = j;
printf("\n");
i++;
}
for (k = 0; k < i; k++)
{
printf("\tPhrase %i : ", k);
for (j = 0; j < length[k]; j++)
{
printf("%c", lines[k][j]);
}
printf("\n");
}
return 0;
}
I'm trying to make a simple encryption program with C. My aim is to translate abc (it can be any word) to 123. Then multiply 2 and get 246 then again translate to text, then write on screen bdf. Here is my algorithm which is not working correctly. I entered abc and I got cbc. Can you help me?
int main()
{
int z,o,c,l,i,j,k,*D;
char word[10];
char alfabe[24]={'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','r','s','t','u','v','y','z','\0'};
printf("enter word");
scanf("%s",word);
c=strlen(word);
printf("has %d letters ", c);
D = (int *) malloc( sizeof(int)*c );
for(i=0;i<c;i++) {
for(j=0;j<26;j++) {
if(word[i]==alfabe[j]) {
D[i]=2*(j+1);
break;
}
}
}
printf("\nlast form before translation ");
for(l=0;l<c;l++) {
printf("%d",D[l]); /*it s just for control */
}
for(z=0;z<c;z++){
printf("%c",alfabe[o]);
o=D[z];
word[z]=alfabe[o] ; break; }
printf("\nnew form of word: ");
for(k=0;k<c;k++) {
printf("%c",word[k]);
}
scanf("%d");
}
The problem is in the following loop.
for(z=0;z<c;z++){
printf("%c",alfabe[o]);
o=D[z];
word[z]=alfabe[o] ;
break;
}
Why did you break? It just translates first character. Second, you need to subtract 1 to get the right index of alphabet array(to redo the addition you did).
word[z]=alfabe[o-1];
Third, you are using o before initializing it? Your compiler should warn you for this.
Fourth, why are you storing 27 characters in char array of size 24?
char alfabe[24]={'a','b',...........,'\0'}
And last but not least you need to use modular arithmetic, this wont work if user enters something like xyz.
OK, first of all '\0' marks the end of an inputed string, you don't need to encrypth this particular character, my suggestion is to place it first in the alfabet so you would get:
alfabet[24] = {'\0', 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','r','s','t','u','v','y','z'};
This will save you the trouble of substracting 1, so you will have:
for (i = 0; i < c; i++)
{
for (j = 0; j < 24; j++)
{
if (word[i] == alfabet[j])
{
D[i] = 2 * j;
}
}
}
In the part where you encode the input. And when you generate the output word:
for (z = 0; z < c; z++)
{
printf("%c", alfabet[D[z]]);
word[z] = alfabet[D[z]];
}
No need for o and especially no break; in the loop.
A more efficient way would be to create a function that handles the encryption of the string passed:
char* getEncryptedWord(char* word)
{
char alfabet[25]={'\0', 'a','b','c','d','e','f','g','h','i','j','k','l','m','n','o','p','r','s','t','u','v', 'x', 'y','z'};
int i, j;
int size = strlen(word);
char* encryptedWord = (char*) malloc(size + 1);
for (i = 0; i < size; i++)
{
for (j = 0; j <= 25; j++)
{
if (word[i] == alfabet[j])
{
if (2 * j > 25)
encryptedWord[i] = alfabet[2 * j % 25];
else
encryptedWord[i] = alfabet[2 * j];
break;
}
}
}
encryptedWord[size] = '\0';
return encryptedWord;
}
I've added 'x' in the alfabet - that is the reason why now there are 25 elements. I'm sure there is one character of the English alphabet missing, but it's 3 AM here and English isn't my primary language. Also, this solution is working on the assumption that the alfabet you provided are the only characters that are supposed to exist in the input and output.
(tip: If you only expect letters A-Z, you don't need to loop through the array to find the corresponding number, you may simply get the number by subtracting the numerical value of 'a', and add 1, if you want the letter 'a' to map to 1.)
Modulo arithmetic is mentioned, but that will give you problems because you will loose the 1:1-mapping, i.e. two letters can end up being translated to the same number.