Vinnaren i pepparkakshustävlingen!
2021-08-24, 18:48
  #1
Medlem
Hej.
Hade tentamen i fredags och fastnade på en uppgift som jag sedan försökt lösa, men jag lyckas inte helt.
Mycket eftersom jag inte verkar förstå helt hur iteratorer kan användas.

Vad som följer är först min funktion, "rovarsprak" och sedan main som testar min funktion.
Min funktion tar 3 argument. iterator.begin(), iterator.end) samt en 3:e iterator?. I första fallet en back_insterter.
back_inserter som jag förstår fungerar genom att man skickar med den som en referens och skriver till den i sin funktion, men den skriver vidare till en sträng som deklarerats i main.

I andra testet blir jag osäker. Jag förstår inte helt vad den ska testa. Vilken distance är det frågan om?
Här hänger jag inte riktigt med.

Kod:
#include <iterator>
#include <vector>
#include <string>
#include <iostream>

using std::cout;
using std::endl;

bool isvowel(char ch) {
	return (ch == 'a') || (ch == 'e') || (ch == 'i') || (ch == 'o') || (ch == 'u');
	}
	
template <class It, class T>

T rovarsprak( It first, It last, const T &value )

{
	
	std::vector<char> rovStr;	// create a temporary char vector to hold the string, converted to rovarspraket

    while( first != last ) {
        // check to see if it's alphanumerical(ie a character) NOT a vowel. Then it must be a konsonant
		if(isalpha(*first) && !isvowel( (char)tolower(*first) ) ){
			rovStr.push_back(*first);
			rovStr.push_back('o');
			rovStr.push_back(*first);
        }
		
		else{
			rovStr.push_back(*first);
		}
		
        ++first;
    }
	
	std::copy(rovStr.begin(), rovStr.end(), value);	// copy all characters to value reference
	
	return value;


}




bool print_and_check(const std::string& s, const std::string& r)
{
    std::string r1;
    auto i1 = std::back_inserter(r1);

    rovarsprak(s.begin(), s.end(), i1);

    auto success = true;
    cout << s << " --> " << r1 << endl;
    if (r1 != r) {
        cout << "*** expected: " << r << endl;
        success = false;
    }

    return success;
}

int main()
{
	// first test
    print_and_check("Test!", "ToTesostot!");
    print_and_check("ABBA", "ABoBBoBA");
    print_and_check("A secret message", "A sosecocroretot momesossosagoge");
    print_and_check("1234", "1234");





	// second test
    std::vector<char> v{'T', 'e', 's', 't', 'i', 'n', 'g', ',', ' ', 't', 'e', 's', 't', 'i', 'n', 'g', ' ', '1', '2', '3',};
    std::string exp = "ToTesostotinongog, totesostotinongog 123";	// 40 characters long
    const auto sz = exp.size();	// 40
    std::vector<char> res(sz+50);	// char vector 40+50 = 90 elements large
	
    auto it = rovarsprak(v.begin(), v.end(), res.begin());	//

    res.erase(it, res.end());

    for (auto x : res) {
        cout << x;
    }
    cout << "\n";

    if(it != res.begin() + static_cast<std::vector<char>::difference_type>(sz)){
        auto d = std::distance(res.begin(), it);
        cout << "*** wrong value of returned iterator. Distance was: " << d << ", expected " << sz << ".\n";
    }

    auto eq = std::equal(exp.begin(), exp.end(), res.begin());
    if(!eq){
        cout << "*** expected " << exp << "\ngot          " << std::string(res.begin(), res.end()) << "\n";
    }
	
	
}
Citera
2021-08-24, 19:53
  #2
Medlem
Citat:
Ursprungligen postat av dagsvag
Hej.
Hade tentamen i fredags och fastnade på en uppgift som jag sedan försökt lösa, men jag lyckas inte helt.
Mycket eftersom jag inte verkar förstå helt hur iteratorer kan användas.

Vad som följer är först min funktion, "rovarsprak" och sedan main som testar min funktion.
Min funktion tar 3 argument. iterator.begin(), iterator.end) samt en 3:e iterator?. I första fallet en back_insterter.
back_inserter som jag förstår fungerar genom att man skickar med den som en referens och skriver till den i sin funktion, men den skriver vidare till en sträng som deklarerats i main.

I andra testet blir jag osäker. Jag förstår inte helt vad den ska testa. Vilken distance är det frågan om?
Här hänger jag inte riktigt med.

Kod:
#include <iterator>
#include <vector>
#include <string>
#include <iostream>

using std::cout;
using std::endl;

bool isvowel(char ch) {
	return (ch == 'a') || (ch == 'e') || (ch == 'i') || (ch == 'o') || (ch == 'u');
	}
	
template <class It, class T>

T rovarsprak( It first, It last, const T &value )

{
	
	std::vector<char> rovStr;	// create a temporary char vector to hold the string, converted to rovarspraket

    while( first != last ) {
        // check to see if it's alphanumerical(ie a character) NOT a vowel. Then it must be a konsonant
		if(isalpha(*first) && !isvowel( (char)tolower(*first) ) ){
			rovStr.push_back(*first);
			rovStr.push_back('o');
			rovStr.push_back(*first);
        }
		
		else{
			rovStr.push_back(*first);
		}
		
        ++first;
    }
	
	std::copy(rovStr.begin(), rovStr.end(), value);	// copy all characters to value reference
	
	return value;


}




bool print_and_check(const std::string& s, const std::string& r)
{
    std::string r1;
    auto i1 = std::back_inserter(r1);

    rovarsprak(s.begin(), s.end(), i1);

    auto success = true;
    cout << s << " --> " << r1 << endl;
    if (r1 != r) {
        cout << "*** expected: " << r << endl;
        success = false;
    }

    return success;
}

int main()
{
	// first test
    print_and_check("Test!", "ToTesostot!");
    print_and_check("ABBA", "ABoBBoBA");
    print_and_check("A secret message", "A sosecocroretot momesossosagoge");
    print_and_check("1234", "1234");





	// second test
    std::vector<char> v{'T', 'e', 's', 't', 'i', 'n', 'g', ',', ' ', 't', 'e', 's', 't', 'i', 'n', 'g', ' ', '1', '2', '3',};
    std::string exp = "ToTesostotinongog, totesostotinongog 123";	// 40 characters long
    const auto sz = exp.size();	// 40
    std::vector<char> res(sz+50);	// char vector 40+50 = 90 elements large
	
    auto it = rovarsprak(v.begin(), v.end(), res.begin());	//

    res.erase(it, res.end());

    for (auto x : res) {
        cout << x;
    }
    cout << "\n";

    if(it != res.begin() + static_cast<std::vector<char>::difference_type>(sz)){
        auto d = std::distance(res.begin(), it);
        cout << "*** wrong value of returned iterator. Distance was: " << d << ", expected " << sz << ".\n";
    }

    auto eq = std::equal(exp.begin(), exp.end(), res.begin());
    if(!eq){
        cout << "*** expected " << exp << "\ngot          " << std::string(res.begin(), res.end()) << "\n";
    }
	
	
}

Distansen de frågar efter är avståndet mellan början och slutet på din sträng, de vill att den är 40, dvs att du returnerar en iterator som pekar på 1 steg förbi sista elementet.

Du har returnerat iteratorn som skriver ut tecken med copy. Vilket om du kollar dokumentation för copy ( https://en.cppreference.com/w/cpp/algorithm/copy ), pekar på första elementet av resultatet.

De mäter alltså första elementet till första elementet, dvs 0.

Om du fortsätter läsa om copy, under returvärde så ser du att den returnerar en iterator som pekar 1 steg förbi slutet på destinationen.

Så, på rad 36
Kod:
return std::copy(rovStr.begin(), rovStr.end(), value);
Citera
2021-08-24, 19:58
  #3
Medlem
Citat:
Ursprungligen postat av fatr
Distansen de frågar efter är avståndet mellan början och slutet på din sträng, de vill att den är 40, dvs att du returnerar en iterator som pekar på 1 steg förbi sista elementet.

Du har returnerat iteratorn som skriver ut tecken med copy. Vilket om du kollar dokumentation för copy ( https://en.cppreference.com/w/cpp/algorithm/copy ), pekar på första elementet av resultatet.

De mäter alltså första elementet till första elementet, dvs 0.

Om du fortsätter läsa om copy, under returvärde så ser du att den returnerar en iterator som pekar 1 steg förbi slutet på destinationen.

Så, på rad 36
Kod:
return std::copy(rovStr.begin(), rovStr.end(), value);

Wow! Tusen tack. Ja, jag förstod inte att copy returnerade någonting.
Sedan är det en sak som aldrig slagit mig tidigare. En funktion med returvärde behöver man inte fånga i en variabel. Gäller detta alla språk?
Citera
2021-08-24, 21:18
  #4
Medlem
Trollfeeders avatar
Citat:
Ursprungligen postat av dagsvag
Wow! Tusen tack. Ja, jag förstod inte att copy returnerade någonting.
Sedan är det en sak som aldrig slagit mig tidigare. En funktion med returvärde behöver man inte fånga i en variabel. Gäller detta alla språk?

Det finns inget som gäller i alla språk.
Citera
2021-08-24, 22:25
  #5
Medlem
Citat:
Ursprungligen postat av Trollfeeder
Det finns inget som gäller i alla språk.
Nä, det var en lite dum fråga. Ska se vad som gäller i Java och Python. Antingen är det bara jag som inte har så goda kunskaper eller så fungerar det annorlunda i dessa språk. Kan inte minnas.
Citera
2021-08-24, 23:26
  #6
Moderator
Neksnors avatar
Citat:
Ursprungligen postat av dagsvag
Wow! Tusen tack. Ja, jag förstod inte att copy returnerade någonting.
Sedan är det en sak som aldrig slagit mig tidigare. En funktion med returvärde behöver man inte fånga i en variabel. Gäller detta alla språk?
Jag ser inget behov av ett fångsttvång. En funktion med ett returvärde av typen Int blir helt enkelt ett heltal, alltså som exempelvis kodraden
Kod:
42;
Ganska meningslöst om man inte gör något med det, men det kan ju vara så att returvärdet inte är det primära i funktionen.
Tänk dig en funktion som kör lite elak kod. Om allt gick som planerat returneras 0, annars något annat.

En iterator är enkelt uttryckt ett sätt att bläddra igenom något, ungefär som en for-loop.
Citera
2021-08-24, 23:39
  #7
Medlem
Trollfeeders avatar
Citat:
Ursprungligen postat av dagsvag
Nä, det var en lite dum fråga. Ska se vad som gäller i Java och Python. Antingen är det bara jag som inte har så goda kunskaper eller så fungerar det annorlunda i dessa språk. Kan inte minnas.

Nej, det behövs inte i dessa språk. Men det finns måååånga språk.
Citera
2021-08-25, 17:11
  #8
Medlem
Citat:
Ursprungligen postat av Neksnor
Jag ser inget behov av ett fångsttvång. En funktion med ett returvärde av typen Int blir helt enkelt ett heltal, alltså som exempelvis kodraden
Kod:
42;
Ganska meningslöst om man inte gör något med det, men det kan ju vara så att returvärdet inte är det primära i funktionen.
Tänk dig en funktion som kör lite elak kod. Om allt gick som planerat returneras 0, annars något annat.

En iterator är enkelt uttryckt ett sätt att bläddra igenom något, ungefär som en for-loop.
Jo, det är jag med på. Var bara osäker eftersom jag tror att jag alltid fångat returvärdena från funktioner med returvärden.
Tack!

Citat:
Ursprungligen postat av Trollfeeder
Nej, det behövs inte i dessa språk. Men det finns måååånga språk.
Tack!
__________________
Senast redigerad av dagsvag 2021-08-25 kl. 17:14.
Citera
2021-08-26, 02:13
  #9
Moderator
Neksnors avatar
Citat:
Ursprungligen postat av dagsvag
Jo, det är jag med på. Var bara osäker eftersom jag tror att jag alltid fångat returvärdena från funktioner med returvärden.
Tack!


Tack!
Testade nyss (i java) och raden
42;
funkade givetvis inte. Not a statement, vilket jag håller med om. Man kan däremot skriva den lika meningslösa raden
new Integer(42);
Citera

Stöd Flashback

Flashback finansieras genom donationer från våra medlemmar och besökare. Det är med hjälp av dig vi kan fortsätta erbjuda en fri samhällsdebatt. Tack för ditt stöd!

Stöd Flashback