I'am trying to learn c and therefore solving this exercise. My problem is in the part where I have to abbreviate a word. I am using sprintf to convert the integer to a string and write it into my old string. But however I try to achieve it, the last character of the string always gets lost. Why does this happen? Here is the code:
#include <stdio.h>
#include <math.h>
#include <stdlib.h>
void abreviation(char *arr,int length){
if ( length+1 > 10){
char c = arr[length];
sprintf(arr+1, "%d%c", length-1,c);
}
}
int main() {
int n,i,j;
scanf("%d\n",&n);
char **arr = malloc(n*sizeof(char*));
for(i=0; i < n ; i++){
arr[i] = malloc(sizeof(char)*100);
char c;
for ( j=0; (c = getchar()) != '\n' ; j++)
arr[i][j]=c;
arr[i][j+1]='\0';
abreviation(arr[i],j);
}
for(i=0; i < n; i++)
printf("%s\n", arr[i]);
}
I appreciate any help.
The loop you wrote to input the words stop at '\0', at that point j is indexed to '\0', and then in the abreviation function char c = arr[length c will always be \0 and not the last char in the word (arr).
A simple fix is to change
abreviation(arr[i],j);
to
abreviation(arr[i],j-1);
Related
I'm having some trouble understanding a string declaration in C using dynamic memory.
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
char *putText(){
char *s=(char *) malloc(256+sizeof(char));
for(int i=0; *(s+i); i++) *(s+i)=getchar();
return s;
}
void main(){
printf("Write the text: ");
char *s=putText();
printf("%s", s);
}
In this function, I'm trying to declare the string using getchar() in a for loop, but when I try to print the string, it always stops at the third character.
I am still a newbie, so I've probably made some mistake. Can someone help?
The allocated memory in this declaration
char *s=(char *) malloc(256+sizeof(char));
can contain any garbage.
So the condition in the for loop
for(int i=0; *(s+i); i++) *(s+i)=getchar();
does not make a sense.
Instead you could write for example
int c;
for ( size_t i=0; i + 1 < 256 && ( c = getchar() ) != EOF && c != '\n'; i++ )
{
*( s + i ) = c;
}
*( s + i ) = '\0';
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.
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]);
}
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.
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;
}