Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 7 years ago.
Improve this question
I need help! I can't do it. I tried in many ways but non has worked.
At least can someone help me with the LOGIC. Below I will paste my code.
Develop a program with a function that receives an array of chars. The function has to modify the original and copy it exactly to another one but putting two asterisks (**) before each word that is a PALINDROME, a palindrome is a word which reads the same backward or forward (e.g ANNA, KAYAK).
For example,
my best friend anna has a red kayak
my best friend **anna has a red **kayak.
#include <stdio.h>
#include <stdlib.h>
void Cargar(char texto1[])
{
int i=0;
char letra;
do
{
letra=getche();
if(letra != '.')
{
texto1[i]=letra;
i++;
}
}
while (letra != '.' && i<99);
texto1[i]='\0';
}
int main()
{
char texto1[100], texto2[100];
printf("Ingrese texto: ");
Cargar(texto1);
int pos=0, esp_anterior=0, aux1=0, aux2=0, aux3=0, bandera=0;
int i, j, k;
for(pos = 0 ; texto1[pos] != '\0' ; pos++)
{
if( texto1[pos] == ' ')
{
if(bandera==0)
{
if( hay_palindromo(texto1, pos, esp_anterior) == 1)
{
texto2[0]='*';
texto2[1]='*';
for(i=2, j=0; j<pos ; j++ , i++)
{
texto2[i]=texto1[j];
}
aux1=i;
aux2=j;
}
else
{
for(i=0; i<pos; i++)
{
texto2[i]=texto1[i];
}
aux3=i;
}
bandera = 1;
esp_anterior = pos;
}
else
{
if(bandera == 1)
{
if( hay_palindromo(texto1, pos, esp_anterior) == 1)
{
texto2[aux1]='*';
texto2[aux1+1]='*';
for(i=aux1+2, j=aux2; j<pos ; j++ , i++)
{
texto2[i]=texto1[j];
}
aux1=i;
aux2=j;
}
else
{
for(i=aux3; i<pos; i++)
{
texto2[i]=texto1[i];
}
aux3=i;
}
esp_anterior=pos;
}
}
}
}
printf("\n%s", texto2);
return 0;
}
int hay_palindromo(char texto1[], int pos, int esp_anterior)
{
int i, j, bandera=0;
for(i=esp_anterior, j=pos; i<pos; i++, j--)
{
if(texto1[i] == texto1[j])
{
bandera=1;
}
else
{
bandera=0;
break;
}
}
if(bandera==1)
{
return 1;
}
else
{
return 0;
}
}
I would suggest a logic like that:
Take string, separate it by a delimiter - " " (space) in your case with strtok.
Then, send each delimited word to a function that determines whether the string is a palindrome or not.
If the string is palindrome, allocate enough space for the string + "", and copy "" + string into the allocated space, save the current position of your 'cursor' on that array.
Pseudo Example:
"Anna notpali"
char *new_str;
int cursor = 0;
is_palindrome("Anna")
Yes -> new_str = malloc(strlen("Anna") + strlen("**") + 1)
strcpy(&(new_str[cursor]),"**Anna");
cursor += strlen("**Anna");
is_palindrom("notpali")
No -> new_str = realloc(new_str,strlen(" notpali") + 1)
strcpy(&(new_str[cursor])," notpali");
cursor += strlen(" notpali");
// After going through all the words
new_str[cursor] = '\0'
etc, there might be some corner cases to take care of, but this is a basic logic I suggest to approach it.
Related
I have a question regarding an issue with a program in C I am making. I am going to write two different strings next to each other in two columns. I haven't found clear answers to my question since they almost always give examples of numbers with a known length or amount.
I have two strings, with a maximum length of 1500 characters, but to me unknown length. Let's for the sake of learning given them these values:
char string1[] = "The independent country is not only self-governed nation with own authorities.";
char string2[] = "This status needs the international diplomatic recognition of sovereignty.";
I want to write them next to each other, with a column width of twenty characters. I have set the difference between the columns to a regular 'tab'. Like this:
The independent coun This status needs th
try is not only self e international dipl
-governed nation wit omatic recognition o
h own authorities. f sovereignty.
I have tried with the following code but it isn't effective since I can't figure out how to adapt it to the length of the strings. It also just adapted to write five rows. I also get the below error.
Could someone please give me an example of how this could be done, and maybe with a pre-defined c-function in order to avoid using the for-loops.
void display_columns(char *string1, char *string2);
int main()
{
char string1[] = "The independent country is not only self-governed nation with own authorities.";
char string2[] = "This status needs the international diplomatic recognition of sovereignty.";
display_columns(string1,string2);
}
void display_columns(char *string1, char *string2)
{
int i,j;
for(i=0;i<5;i++)
{
for(j=0+20*i;j<20+20*i;j++)
{
printf("%c",string1[j]);
}
printf("\t");
for(j=0+20*i;j<20+20*i;j++)
{
printf("%c",string2[j]);
}
}
}
I guess this is more generic way to do it.
void print_line(char *str, int *counter) {
for (int i = 0; i < 20; i++) {
if (str[*counter] != '\0') {
printf("%c", str[*counter]);
*counter += 1;
}
else { printf(" "); }
}
}
void display_columns(char *string1, char *string2)
{
int counter = 0, counter2 = 0;
while (1) {
print_line(string1, &counter);
printf("\t");
print_line(string2, &counter2);
printf("\n");
if (string1[counter] == '\0' && string2[counter2] == '\0') {
break;
}
}
}
To print a single character, use:
printf("%c",string1[j]);
or
putchar(string1[j]);
This is the reason for the warnings and segmentation fault.
With this fix, the program somewhat works, you just have to print a newline as the last part of the loop:
for(i=0;i<5;i++)
{
for(j=0+20*i;j<20+20*i;j++)
{
putchar(string1[j]);
}
printf("\t");
for(j=0+20*i;j<20+20*i;j++)
{
putchar(string2[j]);
}
putchar('\n');
}
Update: For the function to work with strings of variable lengths, try this:
void display_columns(char *string1, char *string2)
{
int i,j;
int len1 = strlen(string1);
int len2 = strlen(string2);
int maxlen = (len1 > len2) ? len1 : len2;
int numloops = (maxlen + 20 - 1) / 20;
for(i=0; i<numloops; i++)
{
for(j=0+20*i;j<20+20*i;j++)
{
if (j < len1)
putchar(string1[j]);
else
putchar(' '); // Fill with spaces for correct alignment
}
printf("\t");
for(j=0+20*i;j<20+20*i;j++)
{
if (j < len2)
putchar(string2[j]);
else
break; // Just exit from the loop for the right side
}
putchar('\n');
}
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
This question does not appear to be about programming within the scope defined in the help center.
Closed 8 years ago.
Improve this question
How can I refactor this with less code?
This is homework and is cracking a Caesar cipher-text using frequency distribution.
I have completed the assignment but would like it to be cleaner.
int main(int argc, char **argv){
// first allocate some space for our input text (we will read from stdin).
char* text = (char*)malloc(sizeof(char)*TEXT_SIZE+1);
char textfreq[ALEN][2];
char map[ALEN][2];
char newtext[TEXT_SIZE];
char ch, opt, tmpc, tmpc2;
int i, j, tmpi;
// Check the CLI arguments and extract the mode: interactive or dump and store in opt.
if(!(argc == 2 && isalpha(opt = argv[1][1]) && (opt == 'i' || opt == 'd'))){
printf("format is: '%s' [-d|-i]\n", argv[0]);
exit(1);
}
// Now read TEXT_SIZE or feof worth of characters (whichever is smaller) and convert to uppercase as we do it.
for(i = 0, ch = fgetc(stdin); i < TEXT_SIZE && !feof(stdin); i++, ch = fgetc(stdin)){
text[i] = (isalpha(ch)?upcase(ch):ch);
}
text[i] = '\0'; // terminate the string properly.
// Assign alphabet to one dimension of text frequency array and a counter to the other dimension
for (i = 0; i < ALEN; i++) {
textfreq[i][0] = ALPHABET[i];
textfreq[i][1] = 0;
}
// Count frequency of characters in the given text
for (i = 0; i < strlen(text); i++) {
for (j = 0; j < ALEN; j++) {
if (text[i] == textfreq[j][0]) textfreq[j][1]+=1;
}
}
//Sort the character frequency array in descending order
for (i = 0; i < ALEN-1; i++) {
for (j= 0; j < ALEN-i-1; j++) {
if (textfreq[j][1] < textfreq[j+1][1]) {
tmpi = textfreq[j][1];
tmpc = textfreq[j][0];
textfreq[j][1] = textfreq[j+1][1];
textfreq[j][0] = textfreq[j+1][0];
textfreq[j+1][1] = tmpi;
textfreq[j+1][0] = tmpc;
}
}
}
//Map characters to most occurring English characters
for (i = 0; i < ALEN; i++) {
map[i][0] = CHFREQ[i];
map[i][1] = textfreq[i][0];
}
// Sort the map lexicographically
for (i = 0; i < ALEN-1; i++) {
for (j= 0; j < ALEN-i-1; j++) {
if (map[j][0] > map[j+1][0]) {
tmpc = map[j][0];
tmpc2 = map[j][1];
map[j][0] = map[j+1][0];
map[j][1] = map[j+1][1];
map[j+1][0] = tmpc;
map[j+1][1] = tmpc2;
}
}
}
if(opt == 'd'){
decode_text(text, newtext, map);
} else {
// do option -i
}
// Print alphabet and map to stderr and the decoded text to stdout
fprintf(stderr, "\n%s\n", ALPHABET);
for (i = 0; i < ALEN; i++) {
fprintf(stderr, "%c", map[i][1]);
}
printf("\n%s\n", newtext);
return 0;
}
Um, Refactoring != less code. Obfuscation can sometimes result in less code, if that is your objective :)
Refactoring is done to improved code readability and reduced complexity. Suggestions for improvement in your case:
Look at the chunks of logic you've implemented and consider replacing them with in built functions is usually a good place to begin. I'm convinced that some of the sorting you've performed can be replaced with qsort(). However, side note, if this is your assignment, your tutor may be a douche and want to see you write out the code in FULL VS using C's in built function, and dock you points on being too smart. (Sorry personal history here :P)
Move your logical units of work into dedicated functions, and have a main function to perform orchestration.
Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
So I was writing a C program to make use of caesar algorithm using a custom table, where I will give the table and shifting will be done using that table e.g the text "abc" according to table "abc" with key=1 should be ciphered as bca, however i am having difficulty on the last characters if key+index of letter is higher than the length of the table stored here is my code
void encrypt (char table[],char entext[],char text[],int key)
{
int i,j;
int k = strlen(table);
//int result = (key + k);
for (i=0;i<strlen(table);++i)
{
j = 0;
if (text[i]!='\0')
{
while (text[i]!=table[j])
{
j++;
}
if ((j+key)>k)
{
j=(j+key)%k;
//j = (result - j);
}
else
j = j + key;
entext[i] = table[j];
}
}
entext[i+1] = '\0';
puts(entext);
}
int main()
{
char table[100] , text[100] , entext[100] , c;
int i , j , key;
printf("Enter the text : ");
gets(text);
printf("Enter the table : ");
gets(table);
printf("Enter the key : ");
scanf("%d",&key);
encrypt(table,entext,text,key);
system("pause");
return 0;
}
if ((j+key)>k)
should be
if ((j+key)>=k)
Besides, this check is completely unnecessary because of how mod works. I will take the liberty to rewrite your code so it looks nicer:
void encrypt (char table[],char entext[],char text[],int key)
{
int i,j;
int k = strlen(table);
//int result = (key + k);
for (i=0;i<strlen(table);++i)
{
if (text[i]!='\0')
{
for(j=0; text[i] != table[j] ;j++);
entext[i] = table[(j+key)%k];
}
}
entext[i+1] = '\0';
puts(entext);
}
I believe you could make this "table" lookup more efficient by indexing the value of the char itself, but unless you are dealing with pretty big input, this won't really make a difference.
void encrypt (char table[], char entext[], char text[], int key) {
int i,j;
int k = strlen(table);
for (i=0;text[i];++i){
for(j=0;table[j] && text[i]!=table[j];++j)
;
if(table[j]=='\0')//character not find at table
entext[i] = text[i];//Not slide. // or Error?
else {
j += key;
if(j>=k)
j -= k;//j = j % k
entext[i] = table[j];
}
}
entext[i] = '\0';
puts(entext);
}
How to remove all adjacent duplicates in a string in C. say for example..if "caaabbcdd" is the given string then it should remove sequentially as
1. cbbcdd
2. ccdd
3. dd
thus an empty string is returned in the end. Time complexity can be O(n^2) for starting.Can anyone help.
so far this i what i have done
void recursiven2(char *str)
{
int i,j,k,len;
len=strlen(str);
for(i=0;i<len-1;i++)
{
if(str[i]==str[i+1])
{
for(j=i;j<len-2;j++)
str[j]=str[j+2];
str[j]='\0';
}
}
}
You can refer to this. It has a very nice explanation.
Your code is close, but not quite.
It's easier to think about this in terms of "if this character is the same as the previous, drop it". Your code is more like "if this character is the same as the next", if you see the difference.
Also, memmove() just loves this.
Perhaps something like:
void compress(char *str)
{
size_t len = strlen(str);
if(len <= 1)
return;
for(size_t i = 1; i < len; )
{
if(str[i] == str[i - 1])
{
memmove(&str[i], &str[i + 1], (len - (i + 1) + 1);
--len;
}
else
++i;
}
}
There might be an obi-wan error (or two!) in the above, I haven't tested it.
string removeDuplicates(string s) {
int done=0;
while(done==0)
{
int check=0;
for(int i=0;i<s.length();i++)
{
if(s[i]==s[i+1])
{
s.erase(i,2);
check=1;
}
};
if(check==0)
{
done=1;
}
}
return s;
}
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
This is the relevant function:
int computerChoice() {
int x, y;
for (y=0;y<=2;y++) {
for (x=0;x<=2;x++) {
if (matrix[y][x] == 'a') {
return(1);
} else {
matrix[y][x] = 'b';
return(0);
}
}
}
}
And this is the relevant main() code:
char matrix[3][3];
int duplicate1 = 0;
do {
duplicate1 = computerChoice();
} while(duplicate1 == 1);
I'm attempting to scan through a 3x3 two dimensional array and check sequentially if each one is equal to "a". If so I want the function to return a "1" and continue checking. Once it finds an entry that is not equal to "a" it should set that entry equal to b, return 0 and stop looping.
I get some really weird results. If [1][1] has an "a" in it, the function doesn't do anything but just "freezes". If [2][2] has an "a" in it, the function correctly places a "b" in the entry [1][1].
This also happens if other entries are already filled.
Any thoughts?
your implementation seems buggy the code should continue till it is finding 'a' in each cell.If it doesn't find 'a' it should set it to 'b' and return 0. the loop will stop automatically when you return.
If both the loop completes that means every cell in matrix contains 'a'. and you should return 1;
int computerChoice() {
int x, y;
for (y=0;y<=2;y++) {
for (x=0;x<=2;x++) {
if (matrix[y][x] == 'a') {
continue;
}
else {
matrix[y][x] = 'b';
return(0);
}
}
}
return 1;
}
I'm assuming what you mean is "I want to process the entire array, and return 1 if I ever found an a, and 0 otherwise". That can be achieved like so:
int found = 0;
for (size_t i = 0; i != 3; ++i)
{
for (size_t j = 0; j != 3; ++j)
{
if (matrix[i][j] == 'a') { found = 1; }
else { matrix[i][j] = 'b'; }
}
}
return found;
(By changing to ++found, you can also return the number of occurrences of 'a'.)
If on the other hand you want to return 0 as soon as you know there's a non-'a' in your data, it's simpler:
for (size_t i = 0; i != 3; ++i)
for (size_t j = 0; j != 3; ++j)
if (matrix[i][j] != 'a') { matrix[i][j] = 'b'; return 0; }
return 1;
I don't exactly understand what you mean by "return 1 and continue checking". I will assume that you want to scan the whole array, and return 1 if every position is an a; otherwise, return 0 and set the first position that was not an a to b. Here's the code:
int computerChoice() {
int x, y;
for (y=0;y<=2;y++) {
for (x=0;x<=2;x++) {
if (matrix[y][x] != 'a') {
matrix[y][x] = 'b';
return 0;
}
}
}
return 1;
}