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.
Related
I have a C program which is meant to return the repeating characters and their frequencies from a given input string. At the moment, it works fine, however I was wondering if there was a way I could change it so it would return characters in order of appearance, as opposed to alphabetical(?) order.
# include <stdio.h>
# include <stdlib.h>
#include <ctype.h>
# define NO_OF_CHARS 256
char fillCharCounts(unsigned char *str, int *count)
{
int i;
for (i = 0; *(str+i); i++)
count[*(str+i)]++;
return 0;
}
void printDups(unsigned char *str)
{
int *count = (int *)calloc(NO_OF_CHARS,
sizeof(int));
fillCharCounts(str, count);
int dupe_chars = 0;
int i;
for (i = 0; i < NO_OF_CHARS; i++)
if (count[i] > 1) {
printf ("\nDuplicate letter: %c, Occurrences: %d", i, count[i]);
++dupe_chars;
}
if (0 != dupe_chars)
printf ("\n");
else
printf ("\nNo duplicates found\n");
free(count);
}
int main()
{
unsigned char str[15] = "";
printf("Enter a word>");
scanf("%s", str);
printDups(str);
getchar();
return 0;
}
At the moment, if the input string were say "zzbbaa" it would give the output;
"Duplicate: a, count: 2"
"Duplicate: b, count: 2"
"Duplicate: z, count: 2"
How can I change this so the output returns the duplicates in order of appearance in the string?
You can go through the string again, printing out the duplicate the first time it's found.
Here's code as I would write it. There's no need for dynamic allocation of memory -- the count array can go on the stack, and *(str + i) is much better written str[i].
#include <stdio.h>
#include <limits.h>
void printDups(unsigned char *s) {
int count[UCHAR_MAX+1] = {0};
int dupes = 0;
for (int i = 0; s[i]; i++) {
count[s[i]]++;
dupes = dupes || (count[s[i]] > 1);
}
for (int i = 0; s[i]; i++) {
if (count[s[i]] > 1) {
printf("Duplicate letter: %c, Occurrences: %d\n", s[i], count[s[i]]);
count[s[i]] = 0;
}
}
if (!dupes) {
printf("No duplicates found\n");
}
}
int main(int argc, char**argv) {
unsigned char s[] = "hello world";
printDups(s);
}
This is how my code looks right now:
#include <stdio.h>
void print_lines(int n);
int main() {
printf("%i", print_lines(7));
return 0;
}
void print_lines(int n) {
int i;
scanf("%i", &n);
for (i = 1; n != 0; --1)
printf("\n");
}
The aim is that the function prints out as many new lines as the user puts in with the scan f function.
what am I doing wrong?
Here is what you wish:
#include <stdio.h>
void print_lines(int n);
int main() {
print_lines(7);
return 0;
}
void print_lines(int n) {
int i;
for (i = n; i >= 1; --i)
printf("\n");
}
If the return type of print_lines is void, you cannot use it in an expression as if you were using its value.
If you are passing a value (7) to the function, then you need not read it again using scanf.
If you are already printing in print_lines, then you need not use printf in main. Just the function call is enough.
for (i = 1; n != 0; --1) won't get you anywhere. This line alone has too many errors. You are initializing i, testing for n and incrementing 1 (which is not possible in C).
Try reading some basics for better understanding.
Another "trick" might be:
printf("%.*s\n", 7, "\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n");
This would print the first 7 characters from the string of 20 characters given as third argument.
I think a better implementation of what you're trying to get at is this:
#include <stdio.h>
void print_lines(int n);
int main() {
/* take input here (how many lines etc) */
print_lines(7));
return 0;
}
void print_lines(int n) {
int i;
for (i = 0; i < n; ++i)
printf("\n");
}
The variant where you want to use inside of printf would be the following:
#include <stdio.h>
void print_lines(int n);
int main() {
/* take input here (how many lines etc) */
char* lines = print_lines(7);
printf("%s", lines);
free(lines) // <-- important
return 0;
}
char* print_lines(int n) {
int i;
char* res = malloc(sizeof(char) * (n + 1)); // <-- important, for \0 termination
for (i = 0; i < n; ++i)
res[i] = '\n';
res[n] = '\0';
return res;
}
However I'd rather use a more generic approach, where you can get N of any character supplied to the function as a secondary parameter. I'll leave that part to you.
EDIT: Here's a version with a user-created buffer:
#include <stdio.h>
void print_lines(int n);
int main() {
/* take input here (how many lines etc) */
char buf[8]; // if you use GCC you can use char buf[N], these are variable length arrays, if not, use a similar malloc method above
print_lines(7, buf);
printf("%s", buf);
return 0;
}
void print_lines(int n, char buf[]) {
int i;
for(i = 0; i < n; ++i)
buf[i] = '\n';
buf[n] = '\0';
}
And finally, the fantasy solution StoryTeller suggested:
#include <stdio.h>
void most_generic_printN(int n, char c, FILE* f) {
int i;
for(i = 0; i < n; ++i)
fprintf(f, "%c", c);
}
int main() {
most_generic_printN(10, 'a', stdout);
return 0;
}
In the above solution, stdout is the standard output stream, which is what you see as the console. You can redirect this to be a file and such. Play around with it!
"While N goes to 0, print a newline."
void print_lines(int n)
{
while (n --> 0) printf("\n");
}
I need to make a console program that prints the following output :
aaaaaaaaa
abbbbbbba
abcccccba
abcdddcba
abcdedcba
abcdddcba
abcccccba
abbbbbbba
aaaaaaaaa
So I made the following code, wich seems to work :
#include <stdio.h>
#include <string.h>
int main()
{
int c, i = 0, p;
scanf("%d", &c);
int len = c*2-1;
printf("%d\n", len);
char ligne[9];
while (i < len-1){
p = 0;
for (int j = 0; j < c; j++){
ligne[len-1-j] = p+97;
ligne[j] = p+97;
if (j < c && p < i)
p++;
}
printf("%s\n", ligne);
i++;
}
return 0;
}
Which seems to work, but when I replace :
char ligne[9];
By :
char ligne[len];
I obtain the following output :
Your program output contains an invalid UTF8 character.
It seems that the table somehow "expanded" : there are much more than 9 fields in it.
I know that initializing tables with variables aren't allowed in some versions of C, but it ain't a problem for me. so, does anyone know where the prolem come from ?
Your problem is that you're trying to store 9 characters plus a terminal null into the space for 9 characters; this doesn't work.
Remove the - 1 from your calculation of len and ensure that the string is null terminated.
It was only by accident it worked with the fixed length array.
You could also fix the problem by revising the printf() statement to:
printf("%.9s\n", ligne);
or:
printf("%.*s\n", len, ligne);
This doesn't require a null-terminated string any more.
The code in the question prints the top half of the output, but gets stuck printing the same line over and over again on the bottom half of the output. This code fixes that, using the min() inline function to determine the maximum increment to be shown. It also validates the return value from scanf() to ensure that the value in c is reasonable (1..26) — failing silently if it is not OK.
#include <stdio.h>
#include <string.h>
static inline int min(int i, int j) { return (i < j) ? i : j; }
int main(void)
{
int c;
if (scanf("%d", &c) == 1 && c >= 1 && c <= 26)
{
int len = c*2-1;
printf("%d\n", len);
char ligne[len];
for (int i = 0; i < len; i++)
{
int p = 0;
int maxinc = min(len-1-i, i);
for (int j = 0; j < c; j++)
{
ligne[len-1-j] = p + 'a';
ligne[j] = p + 'a';
if (p < maxinc)
p++;
}
printf("%.*s\n", len, ligne);
}
}
return 0;
}
You have to allocate 1 char extra space and explicitely add a NULL terminator to the array ligne.
char ligne[len + 1];
ligne[len] = '\0';
char ligne[len+1];
for(int i=0;i<sizeof(ligne);++i)
ligne[i]=0;
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]
I'm parsing a text file:
Hello, this is a text file.
and creating by turning the file into a char[]. Now I want to take the array, iterate through it, and create an array of arrays that splits the file into words:
string[0] = Hello
string[1] = this
string[2] = is
This is my code:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "TextReader.h"
#include <ctype.h>
void printWord(char *string) {
int i;
for (i = 0; i < strlen(string); i ++)
printf("%c", string[i]);
printf("\n");
}
void getWord(char *string) {
char sentences[5][4];
int i;
int letter_counter = 0;
int word_counter = 0;
for (i = 0; i < strlen(string); i ++) {
// Checks if the character is a letter
if (isalpha(string[i])) {
sentences[word_counter][letter_counter] = string[i];
letter_counter++;
} else {
sentences[word_counter][letter_counter + 1] = '\0';
word_counter++;
letter_counter = 0;
}
}
// This is the code to see what it returns:
i = 0;
for (i; i < 5; i ++) {
int a = 0;
for (a; a < 4; a++) {
printf("%c", sentences[i][a]);
}
printf("\n");
}
}
int main() {
// This just returns the character array. No errors or problems here.
char *string = readFile("test.txt");
getWord(string);
return 0;
}
This is what it returns:
Hell
o
this
is
a) w
I suspect this has something to do with pointers and stuff. I come from a strong Java background so I'm still getting used to C.
With sentences[5][4] you're limiting the number of sentences to 5 and the length of each word to 4. You'll need to make it bigger in order to process more and longer words. Try sentences[10][10]. You're also not checking if your input words aren't longer than what sentences can handle. With bigger inputs this can lead to heap-overflows & acces violations, remember that C does not check your pointers for you!
Of course, if you're going to use this method for bigger files with bigger words you'll need to make it bigger or allocate it dymanically.
sample that do not use strtok:
void getWord(char *string){
char buff[32];
int letter_counter = 0;
int word_counter = 0;
int i=0;
char ch;
while(!isalpha(string[i]))++i;//skip
while(ch=string[i]){
if(isalpha(ch)){
buff[letter_counter++] = ch;
++i;
} else {
buff[letter_counter] = '\0';
printf("string[%d] = %s\n", word_counter++, buff);//copy to dynamic allocate array
letter_counter = 0;
while(string[++i] && !isalpha(string[i]));//skip
}
}
}
use strtok version:
void getWord(const char *string){
char buff[1024];//Unnecessary if possible change
char *p;
int word_counter = 0;
strcpy(buff, string);
for(p=buff;NULL!=(p=strtok(p, " ,."));p=NULL){//delimiter != (not isaplha(ch))
printf("string[%d] = %s\n", word_counter++, p);//copy to dynamic allocate array
}
}