I'm having trouble with comparing strings in C. Firstly, I need to find the length of each string from command-line arguments, and then compare them as well as printing the biggest one.
So far, it's just printing the length of each typed string. I need to compare them according to length, not alphabetic order.
I don't understand why is it now working and what I should do fix it? Thank you!
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i, length;
for(i = 0; i<argc; i++)
{
length = strlen(argv[i]);
printf("%s %d\n", argv[i], length);
if(strlen(argv[i]) < strlen(argv[i+1]))
{
printf("%s is the biggest \n", argv[i+1]);
}
else
{
printf("%s is the biggest \n", argv[i]);
}
}
return 0;
}
There are a few problems with your code.
First of all, argv[i+1] is an illegal operation if you're doing i < argc in the for. You need to change i < argc to i < argc - 1 in the for.
Secondly, you are probably not comparing the strings you want. argv[0] is the string representing the path of your program; the first argument passed to your program is argv[1]. Therefore, you need to change the i = 0 in the for to i = 1.
Finally, if you only want the biggest string, you should not do any printing in the for loop. Rather, you should create two variables like max_length and max_length_idx where you would store the length and index of the largest string found so far. Then, after the for loop, your program would print out the string argv[max_length_idx].
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i, max_length, max_index;
max_index = 0;
max_length = strlen(argv[0]);
for(i = 1; i < argc; i++)
{
if(strlen(argv[i]) > max_length)
{
max_length = strlen(argv[i]);
max_index = i;
}
}
printf("The longest is: %s with length equal: %d\n", argv[max_index], max_length);
return 0;
}
This will not segfault ...
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
int i, length;
for(i = 0; i<argc - 1; i++)
{
length = strlen(argv[i]);
printf("%s %d\n", argv[i], length);
if(strlen(argv[i]) < strlen(argv[i+1]))
{
printf("%s is the biggest \n", argv[i+1]);
}
else
{
printf("%s is the biggest \n", argv[i]);
}
}
return 0;
}
Related
Just implementing a simple sorting algorithm to sort a string. I tried printing out the buff char array with printf("%s\n") but it came out blank. The contents of the array are there, though, and I checked with printing out each character of it. What am I missing here?
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char const *argv[])
{
if (argc != 2)
{
printf("usage: ./sortstring string");
exit(1);
}
int size = 1; // 1 to account for '\0'
for (int i = 0; argv[1][i] != '\0'; i++)
{
size += 1;
}
char buff[size];
strcpy(buff, argv[1]);
char temp;
for (int i = 0; i < size; i++)
{
for (int j = i + 1; j < size; j++)
{
if (tolower(buff[i]) > tolower(buff[j]))
{
temp = buff[i];
buff[i] = buff[j];
buff[j] = temp;
}
}
}
// printf("%s\n", buff);
for (int i = 0; i < size; i++)
{
printf("%c", buff[i]);
}
return 0;
}
Change "%c" to "%d" in printf and see the result.
for (int i = 0; i < size; i++)
{
printf("%d", buff[i]);
}
strcpy copies terminating null byte with the source string.
You sorted terminating null byte with other characters.
Your sorting function is probably sorting the null character to position 0.
Instead of attempting to manually count characters in "argc[1]", you could just use the "strlen" function. So, instead of
int size = 1; // 1 to account for '\0'
for (int i = 0; argv[1][i] != '\0'; i++)
{
size += 1;
}
You could use
int size = strlen(argv[1]);
Regards.
The problem is that you're initializing size with 1. I know you did that because you need one more char to \0, but after that, either you need to loop through size - 1 or you can decrease the value of size before your for loops.
Another thing you can do is: initialize size with 0, and use size + 1 while creating your array.
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);
}
I am a beginner so if I miss something vital to the code please forgive me haha. I am making a program which gets input from the console that says how many characters are going to be used, the characters (single letters), and then how long you want the password to be. I feel like I am pretty close, but every time I run the program, it seems to generate a random pattern of letters and I can't follow it.
Here is my code, including the main function.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#define MAX 100
int generatePassword(char* characters[], int i, char s[], int numCharacters, int passwordLength) {
if (i==0) {
printf("%s\n", s);
return 0;
}
for (int j = 0; j < passwordLength; j++) {
strcat(s, characters[j]);
generatePassword(characters, i-1, s, numCharacters, passwordLength);
}
return 0;
}
void homeFunction(char* characters[], int numCharacters, int passwordLength) {
for (int i = 1; i <= numCharacters; i++) {
char s[MAX] = "";
int c = generatePassword(characters, i, s, numCharacters, passwordLength);
}
}
int main (int argc, char *argv[]) {
if (argc < 2) {
printf("ERROR: Program did not execute due to lack of arguments.\n");
return -1;
}
int numCharacters;
numCharacters = atoi(argv[1]);
int passwordLength;
passwordLength = atoi(argv[numCharacters+2]);
for (int i = 0; i < numCharacters; i++) {
if (strlen(argv[i+1]) > 1) {
printf("ERROR: You can only input one character at a time.\n");
return -1;
}
}
if (argv != numCharacters + 3) {
printf("ERROR: Invalid number of arguments.\n");
return -1;
}
char *charArray[numCharacters];
charArray[numCharacters] = (char*)malloc(numCharacters * sizeof(char));
for (int i = 0; i < numCharacters; i++) {
charArray[i] = argv[i+2];
}
homeFunction(charArray, numCharacters, passwordLength);
return 0;
}
In theory, if the user ran the program with "./NAME 2 a b 2" the result should be
a
b
aa
ab
ba
bb
This is my current output. How can I make it look like the output above?
a
ab
abaa
abaab
abaabba
abaabbab
You need to learn the fundamentals of arrays and strings.
Imagine if I run your code as app.exe 99
This is undefined behavior:
numCharacters = atoi(argv[1]);
int passwordLength;
passwordLength = atoi(argv[numCharacters+2]);
If argv[1] is say, "99", then numCharacters will be 99.
Then passwordLength will be assigned the atoi conversion of argv[101]. But there's only two valid elements in argv: argv[0], which is the executable path, and argv[1], which is "99". argv[2] and up is random memory that's not yours to look at.
This is also wrong:
char *charArray[numCharacters];
charArray[numCharacters] = (char*)malloc(MAX * sizeof(char));
You are allocating an array of (string) pointers, then assigning to an index one past the valid range of the array.
I'm looking to replace words from a file where words.txt contains "banana test apple" would output -> "banana Replaced! apple" The words it would be looking to replace would come as an argument to stdin ("test" in this case)
Not sure where my code is going wrong, and I'm also wondering if there's a better way to do it than get getchar() function, as I find it confusing to work with, and annoying as you cannot backup characters.
Any suggestions? Thanks
$ ./a.exe test < words.txt
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char** argv) {
int c = getchar();
int counter = 0;
int i,index;
for (i = 1; i < argc; i++){
for (index = 0; index < strlen(argv[i]); index++){
while (c == argv[i][index]){
counter++;
c = getchar();
index++;
if (counter == strlen(argv[i])){
printf("Replaced!");
}
}
printf("%c ",c);
c = getchar();
counter = 0;
}
}
return (0);
}
I would do it as follows :
read all the file into a buffer using fgets
looking for the key work (test) using strstr
replace it with your new string using strncpy
write to file (or output to stdout) whatever you want to do
You could use scanf to read in a word at a time:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
int main(int argc, char *argv[])
{
char wordbuffer[100];
while (scanf("%99s", wordbuffer) == 1)
{
int replace = 0;
for (int i = 1; i < argc && !replace; i++)
if (strcmp(wordbuffer, argv[i]) == 0)
replace = 1;
if (replace)
printf("Replaced! ");
else
printf("%s ", wordbuffer);
}
}
If you are using a modern system that compliant with the latest POSIX specification, you can take advantage of the m assignment-allocation character, and have the appropriate amount of space allocated for you, so that you don't have to use some arbitrary maximum number of characters.
int main(int argc, char *argv[])
{
char *wordbuffer;
while (scanf("%ms", &wordbuffer) == 1)
{
int replace = 0;
for (int i = 1; i < argc && !replace; i++)
if (strcmp(wordbuffer, argv[i]) == 0)
replace = 1;
if (replace)
printf("Replaced! ");
else
printf("%s ", wordbuffer);
free(wordbuffer);
}
}
I'm attempting to convert command-line arguments into a single char* or "c-string" reference, however it seems my code is breaking. There aren't any compiler warnings, so I'm a bit stuck at this point
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
if (argc < 2) {
printf("usage: program <arguments>");
return 0;
}
char* string = "";
for (int i = 1; i < argc; i++) {
strcat(string, argv[i]);
}
printf("%s", string);
printf("\n");
return 0;
}
Compiling with:
gcc program.c -Wall -std=c99 -o prog
Doesn't seem to throw any warnings, so where could I be going wrong?
Edit:
Updates code to this point:
#include <stdio.h>
#include <string.h>
int main(int argc, char** argv) {
if (argc == 0) {
printf("usage: program <arguments>");
return 1;
}
int tot = 0;
for (int i = 1; i < argc; i++) {
tot += strlen(argv[i]);
}
char string[tot + argc]; // total word length
strcat(string, "\0");
for (int i = 1; i < argc; i++) {
strcat(string, argv[i]);
strcat(string, " ");
}
strcat(string, "\0");
printf("%s", string);
printf("\n");
return 0;
}
However a new problem arises, in that it appears to prepend pseudo-random garbage characters to the string. I added this to the catenation loop to look at the output:
for (int w = 0; w < sizeof(argv[i]); w++) {
printf("\t%s%c\n", "char value: ", argv[i][w]);
}
And this was the output:
./prog one two three
char value: o
char value: n
char value: e
char value:
char value: t
char value: w
char value: o
char value:
char value: t
char value: h
char value: r
char value: e
Tëñ¿one two three
So my guess is that the issue lays within the argument not having a proceeding \0 value, but not 100% certain of how to proceed. Would creating a new array of char to append to, then catenating that be appropriate?
You need to count the total space first:
for (int i = 1; i < argc; i++) {
total += strlen(argv[i]);
}
Then allocate space for final string:
string = calloc(1, total+1);
+1 is for null terminator ('\0').
Then you can strcat to string, and remeber to free it when you don't need it anymore.
Here is the full working code (without error checking):
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
int main(int argc, char** argv) {
int total = 0;
int i;
if (argc < 2) {
printf("usage: program <arguments>");
return 0;
}
char *string;
for (i = 1; i < argc; i++) {
total += strlen(argv[i]);
}
string = calloc(1, total+1);
for (i = 1; i < argc; i++) {
strcat(string, argv[i]);
}
printf("%s", string);
printf("\n");
free(string);
return 0;
}
the way you declare string make the memory that string point to can't be modified.
Instead, you can declare string as char array if you know max size needed. And you'd beter do length checking to make sure it's not overrun when you do strcat
char string[1024]; // put the size you needed
Or you can dynamically allocate space. As suggested by #moeCake.
You're attempting to write into a literal string. Two problems:
1) literal strings aren't generally placed in writable memory.
2) the string (character array) is of size zero; there's no room to write in to it.
The quick answer is to allocate a buffer on the heap:
char* string = (char*)malloc(256);
or on the stack:
char string[256];
Ideally you'd avoid picking a constant size like 256. One approach would be to loop over argv twice - once to measure how much space you'll need, and then again to perform the copies.