C - Better method for replacing - c

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);
}
}

Related

why do I get "Segmentation fault" when assigning values to array of pointers

I have this peace of C Programming code to take multiple literal strings from the user and store each address to each pointer and print out the value
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *ptr[3];
int i = 0;
for (; i < 3; i++) {
printf("ptr_%d: ", i + 1);
fgets(ptr[i], 15, stdin);
ptr[i][strlen(ptr[i]) - 1] = 0;
puts(ptr[i]);
}
return 0;
}
However, only the first one is printed. Here is the output
ptr_1: first line
first line
Segmentation fault
[Program finished]
I want the same result that is produced Here
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *ptr[] = {
"first line",
"second line",
"third line"
};
puts(ptr[0]);
puts(ptr[1]);
puts(ptr[2]);
return 0;
}
output
first line
second line
third line
[Program finished]
Thanks in advance
fgets(ptr[i], 15, stdin);
You've declared an array of three pointers:
char *ptr[3];
But none of those actually point to buffers of memory.
You can either create those buffers automatically:
char ptr[3][15];
Or dynamically with malloc.
char *ptr[3];
for (size_t i = 0; i < 3; i++) {
ptr[i] = malloc(15);
}
If you do this, make sure to free the memory you've allocated.
If you are running gcc (with glibc 2.7 or greater), you can use the m modifier with scanf to allocate memory:
#include <stdio.h>
#include <string.h>
int main(int argc, char *argv[])
{
char *ptr[3];
for (i = 0; i < 3; i++) {
printf("ptr_%d: ", i + 1);
while (scanf(" %m[^\n]",&ptr[i]) != 1)
printf("Try again: ");
puts(ptr[i]);
}
for (; i < 3; i++)
free(ptr[i]);
return 0;
}
And be sure to free the memory when you are done with it.
You'd probably want to put the scanf section of this code into a function but here is the smallest change to your existing sample that should work.
$ cat allocinput.c
#include <stdio.h>
#include <string.h>
#define MAX_LEN 80
int main(int argc, char *argv[])
{
char c;
char ptr[3][MAX_LEN];
int i = 0;
for (;i<3;i++) {
printf("ptr_%d: ", i + 1);
// could overflow if the user types more than MAX_LEN characters
char *p = ptr[i];
while (scanf("%c", &c) && (p - ptr[i] < MAX_LEN)) {
if (c == '\n') break;
*p++ = c;
*p = 0;
}
puts(ptr[i]);
}
return 0;}
$ gcc -Wall allocinput.c
$ ./a.out
ptr_1: first line
first line
ptr_2: second line
second line
ptr_3: third line
third line
$
P.S. I recommend astyle to clean up the formatting:
$ astyle allocinput.c
Formatted /tmp/overflow/allocinput.c
$ cat allocinput.c
#include <stdio.h>
#include <string.h>
#define MAX_LEN 80
int main(int argc, char *argv[])
{
char c;
char ptr[3][MAX_LEN];
int i = 0;
for (; i<3; i++) {
printf("ptr_%d: ", i + 1);
// could overflow if the user types more than MAX_LEN characters
char *p = ptr[i];
while (scanf("%c", &c) && (p - ptr[i] < MAX_LEN)) {
if (c == '\n') break;
*p++ = c;
*p = 0;
}
puts(ptr[i]);
}
return 0;
}

Struggling with wraparound counting in C

I'm a newbie, so apologies if I don't explain myself well. If it helps, I'm doing this for the Caesar problem set as part of the Harvard CS50x OpenCourseWare.
I'm trying to convert user generated plain text to cipher text using a simple key. To accomplish this I'm attempting to use a wraparound counting formula in my last function. However, sometimes I get blanks that print out instead of the new characters... Help!
EDIT: I'm using a key of 5 and the plaintext "Helloz!" to test. Expect to see Mjqqte!
instead am seeing blank spaces.
#include <stdio.h>
#include <cs50.h>
#include <string.h>
#include <math.h>
#include <ctype.h>
#include <stdlib.h>
int convert(string n);
string k, text;
char text;
int r, c, t,x;
bool validate(string n);
//int encrypted(string n);
int main(int argc, string argv[])
{
//accept single command-line argument, non negative integer, k with appropriate error
k = argv[1];
if (argc > 1 && argc <= 2)
{
//printf("Success\n%s\n", argv[1]);
// print individual characters of argv[i]
validate(k);
}
else //if wrong input then print error message and main should return 1
{
printf("Usage: ./caesar key\n");
return 1;
}
text = get_string("plaintext:");
t = atoi(k);
printf("%i\n", t);
convert (text);
printf("\n");
}
//output "ciphertext:" without a newline, with the characters roated by k positions
//after output, print a newline and exit by returning 0 from main
bool validate(string n)
{
for (int i = 0; k[i] != '\0'; i++)
{
if (48 <= k[i] && k[i] <= 57)
{
//printf("%c\n", k[i]);
}
else
{
printf("./caesar key\n");
return 1;
// save for later: printf("%s \n", k);
}
}
return r;
}
int convert(string n)
{
//if fits within a range, Reads individual characters
for (int i = 0; i < text[i]; i++)
{
if (isalpha(text[i]))
{
x = text[i];
//printf("%i\n", x);
c = (x+t) % 26;
// printf("%i\n",c);
printf("%c", c);
}
else
{
printf("%i", text[i]);
}
}
return 0;
}
Here's an implementation that could work for you:
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
void convert(char *text, unsigned char k) {
for (unsigned int i = 0; i < strlen(text); i++) {
if (isalpha(text[i])) {
// Contains the 3 leftmost bits, containing the uppercase/lowercase part.
char c = (text[i] / 32) * 32;
// Perform the shifting with modulo on the alphabetic index of the letter.
text[i] = c + ((text[i] % 32) + k) % 26;
}
}
}
int main(int argc, char *argv[]) {
unsigned char k = strtol(argv[1], NULL, 10);
char text[64];
printf("Using key %d.\n", (int) k);
printf("Plaintext: ");
fgets(text, 64, stdin);
// Remove newline.
text[strlen(text) - 1] = 0;
convert(text, k);
printf("Ciphertext: %s.\n", text);
return 0;
}
Test run:
>>> cipher 4
Using key 4.
Plaintext: Test mE Right Away!!1
Ciphertext: Xiwx qI Vmklx Eaec!!1.

How to add 1 to each letter in a string and print?

I am trying to access each character in a string and add 1 to it before printing out the text. Eg. my code will prompt the user for a text ie. hello and it should print that text plus 1 character(i.e. output "ifmmp" when the input is "hello"). From my code below, instead of a for loop, I am trying to use a while loop to do this however I am running into some issues and it doesn't seem to print the response. Any help greatly appreciated.
// Libraries
#include <cs50.h>
#include <stdio.h>
#include <math.h>
#include <string.h>
#include <stdlib.h>
#include <ctype.h>
int main(int argc, string argv[])
{
// If
if (argc == 2 && (atoi(argv[1]) > 0))
for(int i = 0, len = strlen(argv[1]); i < len; i++)
{
char n = argv[1][i];
int digit = isdigit(n);
if (!digit)
{
printf("Usage: ./caesar key\n");
return 1;
}
else
{
string plain = get_string("plaintext: ");
int k = 0;
int len_plain = strlen(plain);
while (len_plain > k)
k++;
char cipher = plain[k];
{
printf("%c\n", cipher);
}
}
}
else
{
printf("Usage: ./caesar key\n");
return 1;
}
}
Your question seems to be:
am trying to access each character in a string and add 1 to it before printing out the text
That can be done in many different ways - here is one example:
#include <stdio.h>
int main(void) {
char str[10] = "hello";
int i = 0;
while(str[i])
{
++str[i]; // Add 1
++i;
}
printf("%s\n", str);
return 0;
}
Output:
ifmmp

How to turn an array from command line into an array of integers?

I'd like to know how I can turn arrays such as {33,44,77,88} or {10,20,30}, that are given given as command line arguments, and turn them from a char to an integer and finally put them into an array of integers.
I've been looking for hours and I cannot find an example where they get the array from the command line and turn it into an integer array.
This is what I had placed at the command line FOO {33,44,77,88} {10,20,30}
My first 4 lines look like this.
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char *argv[]){
Passing in command-line arguments will pass them in as strings and only strings. Therefore, your argv array will look like this: argv = {"./prog", "FOO", "{33,44,77,88}", "{10,20,30}"};. This means that your passed in array will need to be parsed by your program in order to convert it into an integer array. Try using functions like strtok to parse a string based on a delimiter. Then, once you get the individual numbers, i.e. you have parsed "33", you can use atoi to convert this string into an integer. You will need to build your array up manually.
The following code will interpret any arguments starting with '{' and pull any numbers out that are comma delimited.
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
long int* processArray(char* input, int* lng){
int length = 0, i = 0;
while (input[i] != '\0'){
if (input[i] == ',') length ++;
i++;
}
if (length > 0) length ++;
input++;
int j = 0;
long int * out = malloc(length * sizeof(long int));
while(*input != '}'){
while(*input != '\0' && !isdigit(*input)) input++;
if (!isdigit(*input)) break;
out[j++] = strtol(input, &input, 10);
}
*lng = j;
return out;
}
int main(int argc, char ** argv){
int i;
for ( i = 0; i < argc; i++){
// check for variables that look like arrays
if (argv[i][0] == '{'){
printf("Processing '%s'\n", argv[i]);
int l, j;
long int * variables = processArray(argv[i], &l);
printf("Got Array: { ");
for (j = 0; j < l; j++){
printf("%ld%s", variables[j], j == l-1? "" : ", ");
}
printf(" }\n");
}
}
}
Sample output:
./array-args '{ 1, 2, 3 }'
Processing '{1, 2, 3}'
Got Array: { 1, 2, 3 }
i didnt understand your question to 100% but the implementation of what ever you gave will be like this
args.cpp:
#include<iostream>
using namespace std;
int main(int argc, char *argv[])
{
for (int i = 0; i < argc; ++i)
{
std::cout << argv[i] << std::endl;
}
return 0;
}
compilation and output :
~/c++practise>g++ args.cpp
~/c++practise> ./a.out {33,44,77,88} {10,20,30}
./a.out
33
44
77
88
10
20
30

comparing length of strings C

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;
}

Resources