Program doesn't work after it loops the second time - c

My program below is trying to add the usernames from the "Usernames.text" to the API url. The first username works and makes the url "https://api.1234ng.com/users/profiles/planeraft/Username1" but once it loops back it makes the url always "https://api.1234ng.com/users/profiles/planeraft/" instead of adding the next username in the file.
My code:
#include <stdio.h>
#include <string.h>
int Counter;
int UsernameSize;
char Username[255];
char Request[255]="https://api.1234ng.com/users/profiles/planeraft/";
FILE *UsernamesFile;
int main() {
UsernamesFile = fopen("Usernames.text", "r");
while (Counter < 100) {
fgets(Username, 255, UsernamesFile);
UsernameSize = strlen(Username);
for (int z; z < UsernameSize; z++) {
Request[48 + z] = Username[z];
}
printf("%s", "\n");
printf(Request);
for (int a; a < UsernameSize; a++) {
Request[48 + a] = '\0';
}
Counter++;
}
fclose(UsernamesFile);
return 0;
}

Variables a and z in the for loops are not initialized and thanks to DiKetarogg for some improvements to the code.

Several errors fixed below, more improvements are possible, see comments above and in code below:
#include <stdio.h>
#include <string.h>
int Counter = 0; // need to init
int UsernameSize;
char Username[255];
char Request[255]="https://api.test.com/users/profiles/test/";
// 01234567890123456789012345678901234567890
// 1 2 3 4
FILE *UsernamesFile;
int main() {
UsernamesFile = fopen("Usernames.text","r");
while(Counter < 3) {
fgets(Username, 255, UsernamesFile);
strcat(Request, Username);
UsernameSize = strlen(Username);
Username[UsernameSize-1] = '\0'; // remove <cr>
for(int z=0; z < UsernameSize; z++) {
Request[41+z]=Username[z];
}
printf("%s\n", Request);
Counter++;
strcpy(Request, "https://api.test.com/users/profiles/test/");
}
fclose(UsernamesFile);
return 0;
}

Related

Unique character count function does not take into consideration all lines (C)

My goal is to write a function, that calculates the number of all the unique characters from a redirected text file (meaning until EOF is reached). The code I wrote:
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#define ASCII_VALS 128
int strLen (char inp[])
{
int len = 0;
for(int i = 0; inp[i] != '\0'; i++){
len++;
}
return len;
}
int countUniqueChars (char inp[])
{
int everyCharValArr[ASCII_VALS] = {0};
int i, j = 0;
for(i = 0; i < strLen(inp); i++){
int convToInt = inp[i] - '0';
everyCharValArr[convToInt] = 1;
}
for (i = 0; i < ASCII_VALS; i++) {
j += everyCharValArr[i];
}
return j;
}
works for one string entered via scanf() like so:
int main ()
{
char inp[100];
printf("Enter a string: \n");
scanf("%99s", inp);
printf("%d\n", countUniqueChars(inp));
return 0;
}
But after I change the main function to read a redirected text file, like so:
int main ()
{
char inp[100];
int total = 0;
while(fgets(inp, 100, stdin)){
total += countUniqueChars(inp);
}
printf("%d\n", total);
return 0;
}
and runinng the program (./binary <input.txt) on a input.txt file with contents below:
Toydolls
Flies
trees
rocks
things
the value becomes 26, which is correct (1. word = 6 unique chars, 2. word = 5 unique chars, 3. word = 4 unique chars, 4. word = 5, 5. word = 6 unique chars), but it obviously does not take into consideration chars that appear on more lines, which should not be counted as unique chars at all. My question is How do I fix the function to accomplish this?
Try something like that: Note that I've added a mechanism not to count a duplicate uppercase letter and its lower case letter as unique.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
#include <ctype.h>
#define ASCII_VALS 128
int everyCharValArr[ASCII_VALS] = {0};
int strLen (char inp[])
{
int len = 0;
for(int i = 0; inp[i] != '\0'; i++){
len++;
}
return len;
}
void FindUniqueChars (char inp[])
{
int i;
for(i = 0; i < strLen(inp); i++){
if (inp[i] > ' ' && inp[i] != (char)127)
{
if (inp[i] >= 'A' && inp[i] <='Z')
{
inp[i] = tolower(inp[i]);
}
everyCharValArr[(int)inp[i]] = 1;
}
}
}
int CountUniqueChars( void )
{
int i, j = 0;
for (i = 0; i < ASCII_VALS; i++) {
j += everyCharValArr[i];
}
return j;
}
int main ()
{
char inp[100];
while(fgets(inp, 100, stdin)){
FindUniqueChars(inp);
}
printf("%d\n", CountUniqueChars());
return 0;
}

dynamic allocation string C

I want the user to enter 3 names, and right after the program prints these 3 names
can someone tell me why is not printing anything???
I tried everything
if someone could explain it.....
there is no error, it simply exits after inserting the strings
#include <stdio.h>
#include <stdlib.h>
int main(){
int i, a, componentes;
char *nome;
componentes = 3;
nome = (char*) malloc(sizeof(char)*100);
printf("\n");
for(i = 0; i < componentes; i++){
// printf("String %d: ", i+1);
scanf("%s", &nome[i]);
}
printf("\n");
for(a = 0; a < componentes; a++){
printf("%s\n", nome[i]);
}
return 0;
}
I fixed the issues raised (plus free'ing the memory):
#include <stdio.h>
#include <stdlib.h>
#define N 3
#define LEN 100
int main() {
char *components[N];
for(int i = 0; i < N; i++) {
components[i] = malloc(LEN);
fgets(components[i], LEN, stdin);
}
for(int i = 0; i < N; i++) {
printf("%s", components[i]);
free(components[i]);
}
return 0;
}
You could also allocate the 300 bytes for the 3 strings via local variable on the stack, either with char components[N][LEN]; or as a single string that you index just to show you a different way:
#include <stdio.h>
#include <stdlib.h>
#define N 3
#define LEN 100
int main() {
char components[N * LEN];
for(int i = 0; i < N; i++) {
fgets(components + i * LEN, LEN, stdin);
}
for(int i = 0; i < N; i++) {
printf("%s", components + i * LEN);
}
return 0;
}

strcmp returns __strcmp_sse2_unaligned () in a simple string search programme

I am currently fighting with a primitive search routine. It uses strcmp to compare a string given against a two dim array of strings.
GDP returns:
"__strcmp_sse2_unaligned () at ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S:30 30 ../sysdeps/x86_64/multiarch/strcmp-sse2-unaligned.S: No such file or directory".
Edited: Trying to move on, added command line for string input procedure. Somehow, it is mistaken.
here is my code
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char dictionary()
{
char **strings = (char**)malloc(5*sizeof(char*));
int i = 0;
for(i = 0; i < 5; i++){
//printf("%d\n", i);
strings[i] = (char*)malloc(7*sizeof(char));
}
sprintf(strings[0], "mark");
sprintf(strings[1], "ala");
sprintf(strings[2], "wojtek");
sprintf(strings[3], "tom");
sprintf(strings[4], "john");
for(i = 0; i < 5; i++){
printf("Line #%d(length: %lu): %s\n", i, strlen(strings[i]),strings[i]);
}
for(i = 0; i < 5; i++){
free(strings[i]);
}
free(strings);
}
int cmp(char *s1, char *s2[][10]){
int i = 0;
//size_t l = strlen(s1);
for (i = 0; i < 5; i++){
if (strcmp(s1, s2[i][7*sizeof(char)]) == 0)
{
printf("OK \n");
} else {
printf("sth is wrong \n");
}
return 0;
}
}
int main(){
char BufText[255];
int n=0;
char sign;
fflush(stdin);
n = 0;
do {
sign = getchar();
BufText[n ++] = sign;
if(n >= 253) break;
} while (sign !='\n');
BufText [n] = 0;
char **dict = dictionary();
cmp(BufText, dict);
free_dictionary(dict);
return 0;
}
As said in the comments, there's a lot of flaws in your code.
First in your main, you're trying to cmp("ala", dictionary); but dictionary is an undeclared variable. I think you wanted to use the result of your dictionary() call into the cmp call. So you need to store the dictionary() result into your dictionary variable. It can't actually be done because your dictionary() func does not return anything and free the allocated dict before it can be used.
I could continue this way but here's a patched version of your code. Feel free to ask for clarifications.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
char **dictionary()
{
char **dict = (char**)malloc(sizeof(char*) * 5);
int i = 0;
for (i = 0; i < 5; i++)
dict[i] = (char*)malloc(sizeof(char) * 7);
sprintf(dict[0], "mark");
sprintf(dict[1], "ala");
sprintf(dict[2], "wojtek");
sprintf(dict[3], "tom");
sprintf(dict[4], "john");
for (i = 0; i < 5; i++)
printf("Line #%d(length: %lu): %s\n", i, strlen(dict[i]),dict[i]);
return (dict);
}
void free_dictionary(char **dict)
{
for (int i = 0; i < 5; i++)
free(dict[i]);
free(dict);
}
void cmp(char *s1, char *s2[5])
{
int i = 0;
for (i = 0; i < 5; i++)
{
if (strcmp(s1, s2[i]) == 0)
printf("OK \n");
else
printf("sth is wrong \n");
}
}
int main()
{
char **dict = dictionary();
cmp("ala", dict);
free_dictionary(dict);
return (0);
}

String array prints out trash values

So I have an assignment where I should delete a character if it has duplicates in a string. Right now it does that but also prints out trash values at the end. Im not sure why it does that, so any help would be nice.
Also im not sure how I should print out the length of the new string.
This is my main.c file:
#include <stdio.h>
#include <string.h>
#include "functions.h"
int main() {
char string[256];
int length;
printf("Enter char array size of string(counting with backslash 0): \n");
/*
Example: The word aabc will get a size of 5.
a = 0
a = 1
b = 2
c = 3
/0 = 4
Total 5 slots to allocate */
scanf("%d", &length);
printf("Enter string you wish to remove duplicates from: \n");
for (int i = 0; i < length; i++)
{
scanf("%c", &string[i]);
}
deleteDuplicates(string, length);
//String output after removing duplicates. Prints out trash values!
for (int i = 0; i < length; i++) {
printf("%c", string[i]);
}
//Length of new string. The length is also wrong!
printf("\tLength: %d\n", length);
printf("\n\n");
getchar();
return 0;
}
The output from the printf("%c", string[i]); prints out trash values at the end of the string which is not correct.
The deleteDuplicates function looks like this in the functions.c file:
void deleteDuplicates(char string[], int length)
{
for (int i = 0; i < length; i++)
{
for (int j = i + 1; j < length;)
{
if (string[j] == string[i])
{
for (int k = j; k < length; k++)
{
string[k] = string[k + 1];
}
length--;
}
else
{
j++;
}
}
}
}
There is a more efficent and secure way to do the exercise:
#include <stdio.h>
#include <string.h>
void deleteDuplicates(char string[], int *length)
{
int p = 1; //current
int f = 0; //flag found
for (int i = 1; i < *length; i++)
{
f = 0;
for (int j = 0; j < i; j++)
{
if (string[j] == string[i])
{
f = 1;
break;
}
}
if (!f)
string[p++] = string[i];
}
string[p] = '\0';
*length = p;
}
int main() {
char aux[100] = "asdñkzzcvjhasdkljjh";
int l = strlen(aux);
deleteDuplicates(aux, &l);
printf("result: %s -> %d", aux, l);
}
You can see the results here:
http://codepad.org/wECjIonL
Or even a more refined way can be found here:
http://codepad.org/BXksElIG
Functions in C are pass by value by default, not pass by reference. So your deleteDuplicates function is not modifying the length in your main function. If you modify your function to pass by reference, your length will be modified.
Here's an example using your code.
The function call would be:
deleteDuplicates(string, &length);
The function would be:
void deleteDuplicates(char string[], int *length)
{
for (int i = 0; i < *length; i++)
{
for (int j = i + 1; j < *length;)
{
if (string[j] == string[i])
{
for (int k = j; k < *length; k++)
{
string[k] = string[k + 1];
}
*length--;
}
else
{
j++;
}
}
}
}
You can achieve an O(n) solution by hashing the characters in an array.
However, the other answers posted will help you solve your current problem in your code. I decided to show you a more efficient way to do this.
You can create a hash array like this:
int hashing[256] = {0};
Which sets all the values to be 0 in the array. Then you can check if the slot has a 0, which means that the character has not been visited. Everytime 0 is found, add the character to the string, and mark that slot as 1. This guarantees that no duplicate characters can be added, as they are only added if a 0 is found.
This is a common algorithm that is used everywhere, and it will help make your code more efficient.
Also it is better to use fgets for reading input from user, instead of scanf().
Here is some modified code I wrote a while ago which shows this idea of hashing:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#define NUMCHAR 256
char *remove_dups(char *string);
int main(void) {
char string[NUMCHAR], temp;
char *result;
size_t len, i;
int ch;
printf("Enter char array size of string(counting with backslash 0): \n");
if (scanf("%zu", &len) != 1) {
printf("invalid length entered\n");
exit(EXIT_FAILURE);
}
ch = getchar();
while (ch != '\n' && ch != EOF);
if (len >= NUMCHAR) {
printf("Length specified is longer than buffer size of %d\n", NUMCHAR);
exit(EXIT_FAILURE);
}
printf("Enter string you wish to remove duplicates from: \n");
for (i = 0; i < len; i++) {
if (scanf("%c", &temp) != 1) {
printf("invalid character entered\n");
exit(EXIT_FAILURE);
}
if (isspace(temp)) {
break;
}
string[i] = temp;
}
string[i] = '\0';
printf("Original string: %s Length: %zu\n", string, strlen(string));
result = remove_dups(string);
printf("Duplicates removed: %s Length: %zu\n", result, strlen(result));
return 0;
}
char *remove_dups(char *str) {
int hash[NUMCHAR] = {0};
size_t count = 0, i;
char temp;
for (i = 0; str[i]; i++) {
temp = str[i];
if (hash[(unsigned char)temp] == 0) {
hash[(unsigned char)temp] = 1;
str[count++] = str[i];
}
}
str[count] = '\0';
return str;
}
Example input:
Enter char array size of string(counting with backslash 0):
20
Enter string you wish to remove duplicates from:
hellotherefriend
Output:
Original string: hellotherefriend Length: 16
Duplicates removed: helotrfind Length: 10

Caesar Cipher not returning correct key

So my decrypter program seems to not be able to find the key and implement it by itself. I noticed that if I changed the key to equal -5 which is the correct key it would print out the decrypted text correctly. However I am unable to figure out how to make the program figure it out by itself without having me to put it in manually. Any help would be greatly appreciated! Thank you!
rotUtils.h
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include "rotUtils.h"
int rotate(int c, int n){
if (n == 0) return c;
int nRot = abs(n) % (RANGECHAR + 1);
if(n > 0)
return rotatePlus(c + nRot);
else
return rotateMinus(c - nRot);
}
int rotatePlus(int sum){
int diff = sum - MAXCHAR;
if (sum > MAXCHAR) sum = MINCHAR + diff - 1;
return sum;
}
int rotateMinus(int sum){
int diff = MINCHAR - sum;
if (sum < MINCHAR) sum = MAXCHAR - diff + 1;
return sum;
}
decrypt.cpp
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include "rotUtils.h"
bool solved( char decodearr[], char dictarr[][30], int size1, int size2){
char* compared;
bool result = false;
for(int j = 0; j < size2; j++){
compared = strstr( decodearr, dictarr[j]);
}
if( compared != '\0'){
result = true;
}
return result;
}
int decode( char codearr[], char dictarr[][30], int size1, int size2)
{
bool solution = false;
int key = -50; This is where I had to change it to -5 to solve
char decodearr[10000];
while(solution == false && key < 51)
{
for( int i = 0; i < size1; i++)
{
if(!isspace(codearr[i]))
{
decodearr[i] = rotate(codearr[i], key);
}
else
decodearr[i] = codearr[i];
}
solution = solved( decodearr, dictarr, size1, size2);
if( solution == false)
{
key++;
}
}
for( int j = 0; j < size1; j++)
{
codearr[j] = decodearr[j];
}
return key;
}
int main( int argc, char* argv[])
{
char* file = argv[1];
char* dictionary = argv[2];
char code[10000];
char dict[30000][30];
FILE* codeFile;
codeFile = fopen(file, "r");
int i = 0;
int j = 0;
int key;
FILE* dictFile;
dictFile = fopen(dictionary, "r");
while(!feof(codeFile))
{
code[i] = fgetc(codeFile);
i++;
}
code[ i ]= '\0';
fclose(codeFile);
while(!feof(dictFile))
{
fscanf(dictFile, "%s", dict[j]);
j++;
}
key = decode(code, dict, i, j);
fclose(dictFile);
for(int k = 0; k < i; k++)
{
printf("%c", code[k]);
}
printf( "\nThe key is: %d\n", key);
return 0;
}
Solved() will only return true if there is a match on the last dictionary word currently, you have to move that check inside. You could print to screen whenever you find a key that has a match on your dictionary and/or keep a list of possible keys then print after you are done with them all, right now you would exit as soon as you find any match even if it was just luck.

Resources