Palindrome Program - c

I've created a program that takes an inputted string and outputs the string backwards. I've created a function that counts the number of characters in a string. With that information, I've created another function that puts the first character of the original array at the end of the new array. Thus, when the loop in the function has finished, the new array contains the letters of the original array but backwards. I'm running into some difficulty however. I'm still wary of character arrays and I'm not sure if I'm using them correctly. Could someone help me out?
#include <stdio.h>
#define MAXLINE 1000
char backward(char str[], int count)
int count(char str[])
int main() {
char orig[MAXLINE];
int c;
scanf("%s", orig);
c = count(orig);
printf("%s", backward(orig, c));
return 0;
}
char backward(char str[], int count) {
char back[MAXLINE];
int i;
for(i = 0; i <= count; ++i) {
back[count] = str[i];
--count;
return back;
}
int count(char str[]) {
int i;
for (i = 0; str[i] != '\0'; ++i)
;
return i;
}
Edit: Input: Let's say "minivan". Expected output would be "navinim". There's no actual output yet. I'm getting this error:
palindrome.c:8: error: expected ‘=’, ‘,’, ‘;’, ‘asm’ or ‘__attribute__’ before ‘int’

The error you're getting is because your prototypes are wrong:
#include <stdio.h>
#define MAXLINE 1000
char backward(char str[], int count) /* missing ; */
int count(char str[]) /* missing ; */
int main() {
You should also consider replacing count() with strlen(3) from the <string.h> header file. The standard library is full of utilities that have been debugged and known to work well -- it is worth using them. (Yes, there's educational value in re-implementing them. But in that case, be prepared to test with a variety of corner cases.)

Your code probably won't compile because you missed a closing brace in backward().
char backward(char str[], int count) {
char back[MAXLINE];
int i;
for(i = 0; i <= count; ++i) {
back[count] = str[i];
--count;
/** You should add a } character here! **/
return back;
}
MAJOR EDIT 1:
I tried to compile your code and there were lots of things wrong with it. Here is working code:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAXLINE 1000
char * backward(char * str);
int main() {
char orig[MAXLINE];
int c;
scanf("%s", orig);
printf("%s\n", backward(orig));
return 0;
}
char * backward(char * str) {
int count = strlen(str);
char * back = malloc(MAXLINE);
int i;
for(i = 0; i < count; i++)
{
back[count-i-1] = str[i];
}
back[count] = 0; // Add the null termination character.
return back;
}
When I run this code and enter "abcde", it outputs "edcba". Let me know if you have any specific questions about how this works. I got rid of your count() function because it is a duplicate of strlen(), and I moved the call to strlen() inside the backward() to make the interface to the backward() function simpler.
Another thing that made your code fail is that you were decrementing count inside the for loop, which would cause your for loop to terminate earlier than you wanted it to.

This line has an off by one mistake:
back[count] = str[i];
count is not the last character of the string, it's the '\0' character.
Also you are returning a stack variable - this is not going to work.
You should reverse the string in place:
for(i = 0; i <= count; ++i) {
--count;
char tmp = str[i];
str[i] = str[count];
str[count] = tmp;
}
You can then return str.

You program have lot of errors. Firstly you have missed out semicolons(;) while declaring the prototypes for backward and count. Then you haven't closed the for loop in backward function with ending braces(}).
But the biggest three problems are
1. You have defined backward function as a char data type but you are returning a pointer to the array of char data type
2. You are accessing back[count] instead of back[count-1]. Suppose the string is minivan. The count will hold 7. the last character is at 6th position not 7th because in array subscripts starts with 0 not 1. And back[count] will point to null character i.e '\0'
3. You are incrementing i and decrementing count and checking i<=count. This will process your string only till mid of it.
Although the right program has been posted by David Greyson, but since he have removed the count function and introduced the strlen and malloc function, I am posting your program again by just correcting your algorithm
#include <stdio.h>
#define MAXLINE 1000
char *backward(char str[], int count);
int count(char str[]);
int main() {
char orig[MAXLINE];
int c;
scanf("%s", orig);
c = count(orig);
printf("%s", backward(orig, c));
return 0;
}
char *backward(char str[], int count) {
char back[MAXLINE];
int i;
for(i = 0; i < count; ++i) {
back[count-i-1] = str[i];
}
back[i] = '\0';
return back;
}
int count(char str[]) {
int i;
for (i = 0; str[i] != '\0'; ++i)
;
return i;
}

You can create a character pointer then add length of string to this pointer, it should likely char *reverse = (char *)name, then add reverse = reverse + strlen(name) -1.
Then you can use while loop through through the start of string. The whole code looks,
void main(void)
{
char *name = "Kernel";
char *reverse = (char *)name;
reverse = reverse + strlen(name) - 1;
while(*reverse)
printf("%c", *reverse);
}

#include<Stdio.h>
#include<string.h>
int main()
{
size_t i,j;
char arr[10]={'\0'};//orignal array
char arr2[10]={'\0'};//it's reverse to be
gets(arr);//prompt
strncpy(arr2,arr,10);//copy
strrev(arr2);
if(strncmp(arr,arr2)==0)
printf("plaindrom");
return 0;
}

Related

printing a string in a specific format

So I created have a program that basically prints any given string like that:
Example:
Input:
Hello
Output:
Hello
ello
llo
lo
o
The problem is that for some reason if I use icdiff and compare my output with that output in a text file it says that I am missing elements and that I have more spaces than it should.
Icdiff output:
Hello
ello
llo
As you can see this is clearly different than what I have, but if I test it on the terminal I get the expected output.
Program:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
void print_array(char *p, int tamanho) {
int i;
for (i = 0; i < tamanho; i++) {
printf("%c", p[i]);
}
printf("\n");
}
void nova_str(char *p, char *s, int inicio, int tamanho) {
int i;
for (i = inicio; i < tamanho; i++) {
s[i] = p[i];
}
}
int main() {
char p[1001];
int len;
int j;
scanf("%s", p);
len = strlen(p);
print_array(p, len);
for (j = 1; j < len; j++) {
char *np = (char *)calloc(len + 1, sizeof(char));
nova_str(p, np, j, len);
print_array(np, len);
free(np);
}
return 0;
}
Really any help would be appreciated.
The problem is in the nova_str function: you use the same index into the source and the destination, so the destination array still starts with initcio null bytes which are printed by the print_array and appear as spaces on your system. The array is initialized to all bits zero by calloc().
Here is a much simpler version:
#include <stdio.h>
int main() {
char p[1001];
if (scanf("%1000s", p) == 1) {
for (int i = 0; p[i] != '\0'; i++) {
/* print the word starting at offset i */
printf("%s\n", p + i);
}
}
return 0;
}
calloc() is setting the memory to zero, so you are printing null characters in print_array() when it should be spaces. Replace those null characters with spaces there and this is solved, although I think there is an easier way to achieve what you are trying to do.
If you don't want the letters to be prepended by spaces, add an if (p[i] == '\0') continue; before printf() in print_array() instead.

Program in c crashes

My code seems to crash everytime i run it, i want to make a program that finds a capital letter in a sentence (str[max]) and it prints out how many times it finds it
i get a warning from the build log (warning: 'c' may be used uninitialized in this function) (very entry level programmer here !!)
#include <stdio.h>
#include <string.h>
#include "genlib.h"
#include "simpio.h"
#include "ctype.h"
#define max 26
void checktimes(char str[],char temp);
int main()
{
char str[max], temp;
printf("Type a sentence with 25 characters max :");
gets(str);
int i;
for(i=0;i<=max;i++)
{
temp = str[i];
if(isupper(temp))
checktimes(str,temp);
}
return 0;
}
void checktimes(char str[],char temp)
{
int j,i;
char c;
for(j=0; j<=max ; j++)
{
str[i] = c;
if(c == temp)
i++;
}
printf("%c --> %d",temp,i);
}
You have multiple problems:
1) Never use gets(). Use fgets() instead.
2) You may not always have max number of characters. So, your condition: for(i=0;i<=max;i++) is probably wrong.
Use strlen() to find out the actual number of chars in str.
3) You are reading c uninitialized here:
str[i] = c;
You probably meant:
c = str[j]; /* notice the i -> j change */
4) The argument to isupper() requires a cast to unsigned char.
5) Initialize i to 0 in checktimes().
In fact, there's a logical error as well. You would be printing the count of duplicate chars as many times.
If you use an temp array, it can be written as:
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#define max 26
void checktimes(char str[]);
int main(void)
{
char str[max];
printf("Type a sentence with 25 characters max :");
fgets(str, sizeof str, stdin);
str[strcspn(str, "\n")] = 0; /* To remove the trailing newline if any. */
checktimes(str);
return 0;
}
void checktimes(char str[])
{
int i = 0;
int count[max] = {0};
size_t len = strlen(str);
for(i=0; i<len; i++)
{
if(isupper((unsigned char)str[i]))
count[str[i] - 'A']++;
}
for(i = 0; i < max; i++)
if (count[i])
printf("%c --> %d\n",i+'A', count[i]);
}

Program prints unrelated chars

I wanted to split an array to 2 arrays that the first one contains the lowercased letters of the original array and the second one contains the uppercased letters and from some reason it prints some unrelated chars.
#include <stdio.h>
#include <string.h>
#define LEN 8
int main(void)
{
char str[] = "SHaddOW";
char smallStr[LEN], bigStr[LEN];
int i = 0;
int indexSmall = 0;
int indexBig = 0;
for (i = 0; i <= LEN; i++)
{
if (str[i] <= 'Z')
{
smallStr[indexSmall] = str[i];
indexSmall++;
}
if (str[i] >= 'Z')
{
bigStr[indexBig] = str[i];
indexBig++;
}
}
printf("1: ");
puts(smallStr);
printf("2: ");
puts(bigStr);
system("PAUSE");
return 0;
}
Don't define length before you create the string to test.
Create it's length after defining the string to test.
Copy the characters as you encounter them, but as #Ed Heal says you must add a null terminator so that you can print out the two strings (they aren't really strings until they are null terminated).
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
int main (void)
{
char str[] = "SHaddOW";
int len = strlen(str) +1;
char smallStr[len], bigStr[len];
char term[] = {'\0'};
int n, s, b;
s=0;
b=0;
for(n=0; n<len; n++) {
if(islower(str[n])) {
memcpy(smallStr +s, str +n, 1);
s++;
} else if (isupper(str[n])){
memcpy(bigStr +b, str +n, 1);
b++;
}
}
memcpy(smallStr + s, term, 1);
memcpy(bigStr + b , term, 1 );
printf("Upper: %s\n", bigStr);
printf("Lower: %s\n", smallStr);
}
Output:
Upper: SHOW
Lower: add
Add this to the if structure (and other code to support it)
} else {
memcpy(anyStr +a, str +n, 1);
a++;
}
then:
char str[] = ".S1H2a3d4d5O6W.";
and:
printf("Anything else: %s\n", anyStr);
returns:
Upper: SHOW
Lower: add
Anything else: .123456.
A more compact approach with (perhaps) more meaningful variable names:
#include <stdio.h>
#include <ctype.h>
#include <stdint.h>
#include <string.h>
int main ( void ) {
const char str[] = "SHaddOW";
size_t len = strlen(str); /* better to get actual length */
char lowers[len + 1]; /* add one for the nul char */
char uppers[len + 1]; /* (see below) */
int c;
int i = 0;
int n_upper = 0;
int n_lower = 0;
while ((c = str[i++]) != '\0') {
if (isupper(c)) uppers[n_upper++] = c; /* no need to reinvent */
if (islower(c)) lowers[n_lower++] = c; /* the wheel here */
}
uppers[n_upper] = '\0'; /* the nul char ('\0') marks */
lowers[n_lower] = '\0'; /* the end of a C "string" */
printf("1: %s\n", lowers);
printf("2: %s\n", uppers);
return 0;
}
Notes
If you are super concerned about efficiency you could add an else before if (islower...
Adding const means you "promise" the characters in the array won't be changed.
The type size_t is an integer type, but may be larger than int. It is the correct type for the return of strlen(). It is defined in <stdint.h>. None the less, using int will almost always work (on most systems a string would have to be 'yooooge' for its length to be bigger than an int can hold).
The variable c is declared as int instead of char because int is the proper type for the isXXXXX() functions (which are defined in <ctype.h>). It is also a good habit to get into because of the parallels between this loop and another common idiom while ((c = fgetc(fp)) != EOF) ....
You should consider using isupper() and islower() functions. Code would be cleaner. And what if you have some non alpha characters? Your conditions won't work.
for (i = 0; i < LEN; i++)
{
if (islower(str[i]))
{
smallStr[indexSmall] = str[i];
indexSmall++;
}
else if (isupper(str[i]))
{
bigStr[indexBig] = str[i];
indexBig++;
}
}
As #Ed Heal mention. To avoid printing rubbish, after for loopt you should add a null characters to arrays.
smallStr[indexSmall] = '\0';
bigStr[indexBig] = '\0';

Reverse string with external function

I recently started a course in Programming in C. I got an assignment where I'm going to make an external function with this declaration:
void reverse(char *array, int numberOfChars)
My code looks like this at the moment. The problem is that the code will just reverse the first half of the word, and keep the second half as normal.
#include <stdio.h>
#include <string.h>
void reverse(char *array, int numberOfChars) {
int i = 0;
int j = 0;
for (i = numberOfChars - 1; i >= 0; i--) {
array[j] = array[i];
j = j + 1;
}
}
#define NAMESIZE 100
int main() {
char word[NAMESIZE];
int length;
printf("Enter a word: ");
scanf("%s", word);
getchar();
length = strlen(word);
reverse(word, length);
printf("%s\n", word);
}
Even when you use an intermediate variable, your code will reverse the string twice, leaving it as it was. A small change to the code compares i with j as well as using a temporary variable to do the swap.
int i, j = 0;
char temp;
for(i = numberOfChars-1; i > j; i--){
temp = array[j];
array[j] = array[i];
array[i] = temp;
j = j + 1;
}
Your function has a classic problem: you are reversing the string in place. You overwrite the characters at the start of the string with the characters from the end. The initial characters are lost by the time you reach the mid point. You should instead swap the characters from both ends and stop at the mid point.
You are going to need a secondary char array to reverse the string.Try like this:
#include <stdio.h>
#include <string.h>
#define NAMESIZE 100
void reverse(char *arr,int numberOfChars);
int main()
{
char word[NAMESIZE];
printf("Enter a word: ");
scanf("%s",word);
getchar();
size_t length=strlen(word);
reverse(word,length);
printf("%s\n",word);
}
void reverse(char *arr,int numberOfChars)
{
char buffer[NAMESIZE];
int j = 0,i = numberOfChars;
while( i-- )
buffer[j++] = arr[i];
buffer[j] = '\0';
strcpy(arr,buffer);
}
A simple way to prevent overwriting your array is to copy your array into a temporary one and write the reversed readed temporary array into the other.
If you want to have an unknown array size at compilation to reverse, I recommend you to use a heap array (see man malloc) instead of stack one to prevent segmentation fault if numberOfChars is too hight.

How to transform a block of strings to an array of strings

I've got a block of strings, say "aaa\0bbbb\0ccccccc\0"
and I want to turn them into an array of strings.
I've tried to do so using the following code:
void parsePath(char* pathString){
char *pathS = malloc(strlen(pathString));
strcpy(pathS, pathString);
printf(1,"33333\n");
pathCount = 0;
int i,charIndex;
printf(1,"44444\n");
for(i=0; i<strlen(pathString) ; i++){
if(pathS[i]=='\0')
{
char* ith = malloc(charIndex);
strcpy(ith,pathS+i-charIndex);
printf(1,"parsed string %s\n",ith);
exportPathList[pathCount] = ith;
pathCount++;
charIndex=0;
}
else{
charIndex++;
}
}
return;
}
exportPathList is a global variable defined earlier in the code by
char* exportPathList[32];
when using that function exportPathList[i] contains garbage.
What am I doing wrong?
The answer to this SO question:
Parse string into argv/argc
deals with a similar issue, you might have a look.
You need to know how many strings are there or agree for an "end of strings". The simplest would be to have an empty string at the end:
aaa\0bbbb\0ccccccc\0\0
^^
P.S. is this homework?
First of all, since your strings are delimited by a null char, '\0', strlen will only report the size of the string up to the first '\0'. strcpy will copy until the first null character as well.
Further, you cannot know where the input string ends with this information. You either need to pass in the whole size or, for example, end the input with double null characters:
#include <stdio.h>
#include <string.h>
void parsePath(const char* pathString){
char buf[256]; // some limit
while (1) {
strcpy(buf, pathString);
pathString+=strlen(buf) + 1;
if (strlen(buf) == 0)
break;
printf("%s\n", buf);
}
}
int main()
{
const char *str = "aaa\0bbbb\0ccccccc\0\0";
parsePath(str);
return 0;
}
And you need some realloc's to actually create the array.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#define MAXSIZE 16
char* exportPathList[MAXSIZE] = {0};
size_t pathCount = 0;
void parsePath(char* pathString){
char *ptop, *pend;
ptop=pend=pathString;
while(*ptop){
while(*pend)++pend;
exportPathList[pathCount++]=strdup(ptop);
pend=ptop=pend+1;
}
}
int main(){
char textBlock[]= "aaa\0bbbb\0ccccccc\0";
//size_t size = sizeof(textBlock)/sizeof(char);
int i;
parsePath(textBlock);
for(i=0;i<pathCount;++i)
printf("%s\n", exportPathList[i]);
return 0;
}
The solution I've implemented was indeed adding double '\0' at the end of the string and using that in order to calculate the number of strings.
My new implementation (paths is the number of strings):
void parsePath(char* pathString,int paths){
int i=0;
while (i<paths) {
exportPathList[i] = malloc(strlen(pathString)+1);
strcpy(exportPathList[i], pathString);
pathString+=strlen(pathString);
i++;
}
}
I'd like to thank everyone that contributed.
My Implementation looks like this -> it follows the idea of argv and argc in a main funtion:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(void){
char **args = (char**)malloc(100*sizeof(char));
char buff[100], input_string[100], letter;
for(int i = 0; i < 100; i++){
buff[i] = '\0';
input_string[i] = '\0';
}
for(int i = 0; (letter = getchar())!='\n'; i++){
input_string[i] = letter;
}
int args_num = 0;
for(int i = 0, j = 0; i < 100;i++){
if((input_string[i] == ' ')||(input_string[i]=='\0')){
//reset j = 0
j = 0;
args[args_num] = malloc(strlen(buff+1));
strcpy(args[args_num++],buff);
for(int i = 0; i < 100; i++)buff[i] = '\0';
}else buff[j++] = input_string[i];
}
for(int i = 0; i < args_num; i++){
printf("%s ",args[i]);
}
}
-> Every single word in your string can then be accessed with args[i]

Resources