C++ probleme cu transformarea sirurilor de caractere

Niste explicatii sau algoritmi pentru problemele care presupun transformare sirurilor de caractere in memorie?
De ex: subiectul asta mai exact Subiectul 2 ex 5.
Stiu cum sa separ cuvintele dintr-o prop dar oare am voie sa folsesc un sir auxiliar?Sau am doar un singur sir si trebuie parcurs cu for si while?

trebuie sa spargi acel text in cuvinte. In C exista functia strtok . Dupa ce faci acel lucru trebuie sa numeri cate litere are cuvantul. Daca are nr par de litere inlocuiesti cu “#”

In memorie, adica variabile

https://www.tutorialspoint.com/c_standard_library/c_function_strtok.htm

separatorul pr strtok este spatiu
cu strlen numeri cate caractere are cuvantul.
https://www.tutorialspoint.com/c_standard_library/c_function_strlen.htm

Da, stiu cum se despart cuvintele am rezolvat problema intr-un fel :

#include <iostream>
#include <string.h>
using namespace std;

int main() {

    char sir[101];
    char aux[101]="";
    cout<<"sir: ";cin.get(sir,100);
    char *p,separator[]="?!,. ";
    p=strtok(sir,separator);
    while(p) {
        if(strlen(p) % 2 == 0) {
            strcat(aux,"# ");
        }
        else
        {
            strcat(aux,p);
            strcat(aux," ");
        }
        p=strtok(NULL,separator);
    }
    strcpy(sir,aux);
    cout<<sir<<endl;
    return 0;
}

Dar pot rezolva doar cu un singur sir?fara sa folosesc unul auxiliar

1 Like

Daca programul tau merge eu zic că e un câștig. Aloca mai multa memorie decât trebuie și are complexitatea de timp pătratică in schimb, așa că se poate că “comisia” sa te depuncteze pentru asta. Nu parea sa fie vreo indicație in subiect în sensul asta. Iar la mărimea șirului respectiv de doar 101 caractere, nu o sa fie clar evidențiate problemele astea. În sensul că e o problema mica. Dacă îți dădea de 10000+ caractere devenea o problema.

Sunt pe mobil și e duminică, așa că nu dau decât niște hinturi, nu și cod. Sper sa fie OK.

In schimb, că e propui tu este posibil. Trebuie sa modifici pe sir pe măsură ce îl procesezi de la stânga la dreapta. Aș renunța la strtok deoarece e overkill aici pentru că ai un input foarte bine controlat. Că sa găsești un cuvânt trebuie doar să cauți de la un index până la primul spatiu. Apoi fie înlocuiești prima literă cu # și a doua cu un spatiu și apoi continui scrierea de la a treia în caz că e lungimea para. Fie scrii tot cuvântul în caz că e impar.

2 Likes

la solutia cu index-ul ma gandeam si eu !
:slight_smile:

Totusi, in problema nu exista nicio restrictie de memorie sau de folosire a unei variabile auxiliare
:smiley:

strtok nu e doar overkill, dar si modifica string-ul de intrare (pune ‘\0’ acolo unde sunt separatorii de token), făcând foarte imbârligată modificarea “in place”.

Ca o mică deviaţie de la subiect, am insistat cândva pe const correctness şi asta e de mare ajutor când vrei să-ţi dai seama dacă o funcţie oarecare va interveni asupra variabilelor cu care “hrăneşti” respectiva funcţie. De exemplu, in documentaţia pentru strtok apare aşa:

char *strtok(char *str, const char *delim);

Faptul că nu apare const char *str indica cu o siguranţă foarte mare ca funcţia se va “juca” cu str-ul nostru.

2 Likes

Exista posibilitatea ca in C sa faci replace pe un char fara variabila aditionala ?

Trebuie sa fii mai specific. Dacă te referi la ceva gen str_replace, nu exista in C.

1 Like

La ceva asemanatoar cu str_replace m-am referit
Multumesc !
:slight_smile:

Cred că singurul asemănator care face parte din standard library este std::regex_replace(). Oricum nu prea conteaza, când programezi in C/C++ nu prea te bazezi pe biblioteca standard, ci foloseşti oricum o bibliotecă oarecare, de regula mult mai bogată în opţiuni de manipulare a string-urilor.

Exemple:

FOX Toolkit: FXString
Qt: QString
Glib/Gtk: GString

1 Like
#include <string>
#include <iostream>

int main()
{
	std::string str;

	getline(std::cin, str);

	const int strLen = str.length();

	int writePos = 0;
	int count = 0;

	for (int i = 0; i < strLen; ++i)
	{
		if (str[i] != ' ') ++count;
		else
		{ 
			if (count % 2)
			{
				str[writePos++] = '#';
				str[writePos++] = ' ';				
			}
			else
			{
				for (int j = 0; j <= count; ++j) str[writePos + j] = str[i - count + j];				
				writePos += count + 1;
			}

			count = 0;
		}
	}


	if (count % 2) str[writePos++] = '#';
	else for (;count; --count) str[writePos++] = str[strLen - count];

	str.resize(writePos);

	std::cout << str << std::endl;

	return 0;
}

E pentru cuvinte impare. Deliberat. Modifica-l sa mearga similar pentru cuvinte pare. Asa o sa intelegi mai usor ce se intampla. Ai grija ca l-am scris in vreo 3 secunde (glumesc, dar numai partial) si s-ar putea sa nu fie corect.

Nu e deloc ok sa incerci sa gasesti librarii care sa-ti rezolve problema, cand e vorba de probleme de algoritmica. Deloc. Sper ca te prinzi de ce.

PS Daca gasesti ceva, macar un const de pus pe acolo, explica-mi cum habar nu am. Eventual spune-mi ca sunt arogant ca am incercat sa te ajut. Trebuia sa ma straduiesc mai mult daca e ‘pentru comunitate’, nu? Ei bine, nu. Ideea e acolo, chiar daca codul e gresit. Te prinzi tu. Sau nu.

in cazul lui nu.

de ce vrei sa dezgropi ceva mai vechi ?
trebuia sa te opresti la :

LE: Apreciez ca Serghei zice lucruri in plus utile despre C/C++
LE2: Nu mai este necesar un raspuns !

1 Like

De amuzament. As putea sa dau un citat, dar n-are rost.

Iar tu de ce bagi post-uri off topic?

Puteam sa fac si eu asta. De exemplu puteam sa-ti explic ce tampenie mare poti sa faci daca bagi const-uri peste tot prematur. Nu o sa o mai fac, dar totusi o sa-ti dau un hint:

Un individ pe nume Knuth.

Da. Amuzant.
Pacat ca sa lasat cu suspendare
:slight_smile:
O zi frumoasa !

In caz ca nu iti place al doilea for, poti sa incerci codul asta in schimb:

    for (; count; --count) str[writePos++] = str[i - count];
    str[writePos++] = ' ';

Avantajul ar fi ca e ceva mai usor de inteles si nu foloseste variabila aditionala j. Dezavantajul e ca nu l-am testat deloc :slight_smile:

1 Like